OmniAICreator/Qiita-1.07M huggingface dataset:
Teachable MachineとNode-REDを使って、機械学習させた書類情報をLINEへ送信出来た！

#「書類の提出先」に悩んだことはありませんか？
現在、人事で社内教育や採用を担当しています。
当社は人事と総務が別な部署となっており、私のいる人事は「4階」、総務は「1階」という配置になっています。移動は原則階段というルールがあります。
また、一例に当社での「車の扱い」を挙げると、「通勤は人事」「社有車は総務」と微妙に管轄も違っており、私のチームは座席が入口側にあることから週に10分くらい下記のようなやり取りをしています。

##私に起きている問題
- 「この書類どこに出すの？…え？！総務なら1階じゃん！無駄足だった！」というやり取りの度に仕事の手が止められる。
- 「よく分からないけど、人事っぽい書類だから電話してみた」という入電がある。
- 人事の書類ではあるが担当者までは分からない人に「今の担当は誰？」と声を掛けられる。

#3つの解決したいこと
- 電話や声掛けの度に仕事の手を止められることをなくしたい。
- 社内で無駄なウォーキングをする人を減らしたい。
- 今後、部内の担当者が変わっても提出者自身が迷わず出せるようにしたい。

#解決策（完成品）
書類をwebカメラで読み込むとLINEに「担当部署・担当者名など」が返ってくるようにしました。これで、**提出をする人は1階から4階までを移動する時間や担当者を探す時間、私は週に10分くらいある質問対応がお互いに削減出来ます！**
パソコン上、LINE上の表示は下記の通りとなります。なお、左右別々に撮影したため、本来はパソコン上の表示に合った返答がLINEへタイムリーに送られています。
![Codopenのgif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2490846/049d1a0a-aa9a-d693-c17e-4c6029fa39e0.gif) ![LINEのgif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2490846/920b81a9-c39a-170e-f4f9-0746feb4c40d.gif)

#利用したツール
- Teachable Machine
- CodePen
- LINE Messaging API
- Node-RED

#作業工程
##1. 書類を用意し、Teachable Machineで学習させる
今回は「ノート＝通勤許可申請」「新聞＝社有車使用許可」「webカメラの背景＝確認出来ません」として登録しました。
![キャプチャ111.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2490846/338a01c2-b7d7-281f-ce66-5851db0f143f.png)
##2. CodePenでwebカメラ画像の取得とNode-REDに情報を送るためのコードを作成
<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="dyZogMG" data-user="aoki-risa" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/aoki-risa/pen/dyZogMG">
  提出先チェック！</a> by aoki-risa (<a href="https://codepen.io/aoki-risa">@aoki-risa</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
##3. CodePenとNode-REDを連携
各ノードを編集。LINE上に「担当部署・担当者名など」が送信されるように設定。
![Node-RED.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2490846/640ec2e0-dddd-01de-9ff5-a07e862a4c6c.png)
![ktHIQGlyour4yFoR8ipm1643473776-1643473776.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2490846/bf6a6fa1-4aad-68dd-e603-d898036a3970.gif)

#課題・今後やってみたいこと
- カメラに映る書類が変わった時だけ読み込むようにしたかったのですが、私の書いたコードでは正しく処理が出来ず、苦肉の策で読み込みを3秒に1回に行うことにしました。
- 中々ペーパーレスが進まない当社において総務でよく聞かれる書類もありそうなので、協力したら社内で無駄なウォーキングをする人をもっと減らせるのではないかと思いました。
【TypeScript入門 #4】TypeScriptの色んな型の紹介

# 概要

オンラインサロン IT_KINGDOM で、typescript について学んだことを備忘録としてメモしていきます。

# 学習内容

- 6 つの型の紹介 Array, Tuple, Any, Unknown, Void, Never

## Array 型

- 配列の型を指定できる
- 書き方には`型名[]`と`Array<型名>`の 2 種類がある（`型名[]`の方が一般的らしい）
- 複数の型指定も可能

```typescript
const foo: number[] = [1, 2]; // 型名[]
const foo: Array<number> = [1, 2]; // Array<型名>
const foo: (number | string | boolean)[] = ["a", 1, true]; // 複数の型指定
```

## Tuple 型(タプル型)

- 要素の数や各要素の型を指定することができる
- 要素のメソッドを補完できる
- Tuple 型を使える場合は、Array 型ではなく Tuple 型を使う方が良い

```typescript
const foo: [string, number] = ["fooo", 0.00635]; // Tuple型で配列を宣言
foo[1].toFixed(2); // 配列の2番目の値(0.00635)をメソッドで整形
```

## Any 型

- 型指定しない(基本使わない方が良い)
- 初期に型指定しづらい場合に使う

```typescript
let foo: any = true;
foo = 5; // 別の型を代入してもエラーにならない
```

## Unknown 型

- 型不明の場合に使う（Any 型と近い）
- Any と違って、メソッド等を制御できる

```typescript
const foo: unknown = "foo"; // unknownで型指定
foo.substr(2); // substr()はstring型のメソッドのため、エラーになる
if (typeof foo === "string") {
  foo.substr(2); // if文でstring型に制御しているため、エラーにならない
}
```

## Void 型

- 関数の戻り値がないことを示す

```typescript
const foo = (): void => {
  alert("hello");
  return; // 関数の戻り値なし
};
const foo: () => void = () => {
  alert("hello");
};
```

## Never 型

- 発生しない場合の型に付与

```typescript
const foo = (bar: "a" | "b") => {
  switch (bar) {
    case "a":
      return;
    case "b":
      bar;
      return;
    default:
      bar; // never型（決してここには来ないため）
      break;
  }
};
```

# 参考サイト

[オンラインサロン IT KINGDOM](https://it-kingdom.com/)
AtCoderのPython3.8.2と同じ環境を再現するためのPipfile（2022/1/30時点）

AtCoderのPython3.8.2と同じバージョンのライブラリを入れるためのPipfileを誰かが公開してくれてないかな…と思いましたが、案外見つからなかったので共有しておきます。誰かのためになれば幸いです。
（Pipenvやpyenvのインストール方法や使い方については既に多くの方が解説してくださっているのでここでは割愛します）

### 使い方
1. Pipenvとpyenvをインストールする
1. AtCoder用のディレクトリ直下に下記の内容でPipfileを作成し、`pipenv install -d`する

```:Pipfile
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
autopep8 = "*"
online-judge-tools = "*"
selenium = "*"

[packages]
numba = "==0.48.0"
numpy = "==1.18.2"
scipy = "==1.4.1"
scikit-learn = "==0.22.2.post1"
networkx = "==2.4"

[requires]
python_version = "3.8.2"
```

### 補足
- ライブラリのバージョンは2022年1月30日時点でAtCoderの「コードテスト」にて確認できたものです。
- `[dev-packages]`の`autopep8`はコードの整形用、`online-judge-tools`と`selenium`は入力例での自動テスト用なので、不要な場合は削除してください。

### 参考
- [AtCoderで使用可能なライブラリ（言語別）](https://atcoder.jp/contests/language-test-202001)
【Rails】Unable to autoload constant (module名)::(controller名)Controllerエラーが出た件

#状況

* routing、model、controller、viewを作成し、ローカルでページにアクセスしてみた。
* 以下のエラーが表示された。

```
Unable to autoload constant (module名)::(controller名)Controller, expected 
/(service名)/app/controllers/(controller名)_controller.rb to define it
```
#解決法

コントローラーの内容を module ~ end で囲う。

```ruby:(controller名)_controller.rb
module (module名)
  class (controller名)Controller < ApplicationController
    (コントローラーの内容)
  end
end
```
このような見落としを防ぎたい限りである。
【axios、CORS】headerの値が取得できない

異なるオリジン間でAPIを叩いたときに、axiosでヘッダーの値がなかなか取得できなかった。

```:レスポンスヘッダー（抜粋）
Access-Control-Allow-Origin: http://localhost:3000
Content-Type: text/plain; charset=utf-8
X-Csrf-Token: EWD+CsibPN...
```
```js:クライアント側
//localhost:3000
axios
  .get("http://localhost:8080/token")
  .then(resp => {
    console.log(resp.headers["x-csrf-token"]; // => undefined
    console.log(resp.headers["X-Csrf-Token"]; // => undefined
    console.log(resp.headers["content-type"]; // => text/plain; charset=utf-8
  }))
```

どうやらCORSの仕様で、標準でないヘッダーをjsで取得するには、レスポンスヘッダーに**Access-Control-Expose-Headers**を指定しなければならないらしい。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

```:レスポンスヘッダー（抜粋）
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Expose-Headers: X-CSRF-Token              ← 追加
Content-Type: text/plain; charset=utf-8
X-Csrf-Token: EWD+CsibPN...
```
```js:クライアント側
axios
  .get("http://localhost:8080/token")
  .then(resp => {
    console.log(resp.headers["x-csrf-token"]; // => EWD+CsibPN...
    console.log(resp.headers["X-Csrf-Token"]; // => undefined
    console.log(resp.headers["content-type"]; // => text/plain; charset=utf-8
  }))
```

ちなみにaxiosは["X-Csrf-Token"]のような大文字は使えない。lowerCaseで書く。
Splunk: サーチ結果をブラウザからダウンロードする

よく使うのでメモ。

###### 実施環境： Splunk Free 8.2.2

###### 検索結果の CSV 出力

 Splunk で実行したサーチの結果は、 CSV ファイルとしてブラウザ経由でダウンロードできます。
方法は非常に簡単です。

まずは、 SPL 文の入力フォームの右下にある、下向き矢印のボタン(画像の赤枠で囲っている箇所)を押します。

![スクリーンショット 2021-12-12 18.05.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/f3293faa-a852-6ecf-ec79-cdf071420eba.png "エクスポート")

このボタンを押すと、ダウンロードの設定画面が開きます。

![スクリーンショット 2021-12-12 18.12.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/720b1db7-7364-0b5b-7068-dd4119607a8e.png "エクスポート画面")

フォーマットは XML や JSON も選択できますが、大抵は CSV でダウンロードすることになるかと思います。
ファイル名は拡張子まで含めた指定でも、含めない指定でもよいです。
含めない場合、適宜拡張子が適用されます。
結果数は基本空白でよいですが、ダウンロードする行数を制限したい場合は指定してください。

設定を行ったら、あとはエクスポートボタンを押すだけです。
たったこれだけで、サーチ結果がダウンロードできます。

###### ダッシュボードの CSV 出力

ダッシュボード上のサーチの場合も同様です。
一見ダウンロードボタンがないように見えますが、表やグラフにカーソルを合わせると右下に出てきます(画像の赤枠で囲っている箇所)。

![スクリーンショット 2021-12-12 19.32.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/cf8aa10d-ba68-b89a-efa0-89e6c2c5678e.png "ダッシュボード")

###### 出力ファイルの中身

 CSV の中身は、以下のような感じになります。
 _time が ISO8601 の形式となる点に注意が必要です。
値の形式や列名をきっちり指定したい場合は、 SPL 文中で整形してからダウンロードするようにしましょう。

![スクリーンショット 2022-01-09 14.35.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/70fcf225-b685-55f6-dfde-12ab89d9b0a7.png "CSV")

また、文字コードにも注意が必要です。
特にエクセルで開く際は UTF-8 等だと文字化けしてしまうので、適宜 SJIS に変換する必要があります。

ちなみに、 XML や JSON の場合は以下のような感じです。

![スクリーンショット 2022-01-09 14.41.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/917902d3-4a85-924c-4857-9303fad54c02.png "XML")

![スクリーンショット 2022-01-09 14.42.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/c2fcb9f6-3b25-15d6-9261-a350085f3771.png "JSON")

###### ダッシュボードの PDF 出力

ダッシュボードの場合は、 CSV や XML でのダウンロードのほかに、 PDF でのダウンロードも可能です。
右上の「エクスポート」から、「PDFのエクスポート」を選択してください。

![スクリーンショット 2022-01-09 14.43.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/e1a01c43-d789-e65b-8bfd-5cfd25b7ded3.png "PDFのエクスポート")

「ダッシュボードID-YYYY-MM-DD.pdf」というファイル名で、以下のようなPDFが生成されます。

![スクリーンショット 2022-01-09 14.47.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/adef7e8e-4a05-12a3-8658-cdb0d0abd8be.png "PDF")

表のダウンロードとしては使いにくいですが、グラフをダウンロードするのには便利です。
分断されたエリアのOSPFの挙動を確認

2021年春のネットワークスペシャリストの問題に、分断されたエリアにOSPFを設定するという問題があったので、気になって検証がてら。
今回もCisco Packet Tracerを使っていきます。
![ospf1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667679/2e966354-519e-e71f-e1aa-b2dffa54f793.png)

##Router0の設定
```tex
interface GigabitEthernet0/0
 ip address 1.1.1.1 255.255.255.252

interface GigabitEthernet0/2
 ip address 192.168.0.1 255.255.255.0

router ospf 1
 network 1.1.1.1 0.0.0.0 area 0
 network 192.168.0.1 0.0.0.0 area 1
```
##Router1の設定
```tex
interface GigabitEthernet0/0
 ip address 1.1.1.2 255.255.255.252

interface GigabitEthernet0/1
 ip address 2.2.2.2 255.255.255.252

router ospf 1
 network 1.1.1.2 0.0.0.0 area 0
 network 2.2.2.2 0.0.0.0 area 0
```
##Router2の設定
```tex
interface GigabitEthernet0/1
 ip address 2.2.2.1 255.255.255.252

interface GigabitEthernet0/2
 ip address 192.168.1.1 255.255.255.0

router ospf 1
 network 2.2.2.1 0.0.0.0 area 0
 network 192.168.1.1 0.0.0.0 area 1
```
結果としては分断されたエリアでもPC0とPC1間で問題なく通信ができた。
各ルータで`sh ip route`を実行すると、PC0からPC1へ通信するにはOSPFで学習した経路を使用する事が解る。
![ospf4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667679/9ed76d30-3391-93db-2600-95e8df6b250b.png)

各ルータで`sh ip ospf database`を実行すると、ルーターLSA(タイプ1)でArea 0内にルータが3台、Area 1内にルータが1台ある事が解る。
![ospf2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667679/d3512afd-ae24-fd61-b1a1-59d7e448f734.png)

`show ip ospf neighbor`の実行結果
![ospf3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667679/221d20cb-9768-463d-2bd9-7506db4cbd4b.png)

余談ですが、昔上司が全社ネットワークを3つのハブに対して20以上のスポーク＆AWSのクラウドがぶら下がるハブメッシュのVPNを組んで、全て静的ルーティングを設定していたのですが、OSPF使えば楽なのに。。。と当時は思ったり。
でもヤマハのルータでダイナミックVPNしてたのもあり、Ciscoのような検証用エミュレータも無いし、ただでさえ複雑なネットワークだったしで(NTTの営業の人に世間話がてら話したらドン引きされたw)、結局は単純だけど冗長な静的ルーティングで正解だったのかも(;^ω^)
【Apache】Failed to restart httpd.service エラーの対処方法

#はじめに
EC2を学習用に個人利用しています。仕事では利用していない為、ときどき思い出したかのように、EC2の構築をしてみたりという個人的なAWS利用をしています。今回は、Apacheをインストール後に、EC2を再起動したときに遭遇したエラーについて、対処方法を備忘録として残しておきます。

#何が起きたか
EC2にApacheをインストールして、ドキュメントルートに配置したHTMLファイル（/var/www/html/index.html）をChromeでアクセスし無事に表示されたので安心して、その日はEC2を停止して終わりにしました。翌日、EC2を起動して、Chromeでアクセスしたら、index.htmlが表示されませんでした。

#systemctl restart httpd を実行しても、Apache が起動しない。
なんでだ。。。答えは単純で、root になっていなかったので、起動しなかっただけでした。ただ、起動しなかったときの、エラーメッセージをGoogle検索すると、そんな単純な答えは出てくる訳もなく？、遠回りしてしまいました。

#エラーメッセージ
##以下のエラーメッセージがでました。
```
Failed to restart httpd.service: The name org.freedesktop.PolicyKit1 was not provided by any .service files
```
##httpd の起動状態を調べる
```
[ec2-user@ip-172-31-23-3 html]$ systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:httpd.service(8)
```

##httpd のコンフィグ設定をテストする
```
[ec2-user@ip-172-31-23-3 html]$ service httpd configtest
AH00526: Syntax error on line 43 of /etc/httpd/conf.d/mod_security.conf:
ModSecurity: Failed to open debug log file: /var/log/httpd/modsec_debug.log
```

##AH00526 でGoogle検索するも・・・
何やら難しい記事が出てくるが内容を見ても、そんな変更加えていないなぁ、とちょっと途方に暮れる。

##httpdのログを調査する
```
[ec2-user@ip-172-31-23-3 html]$ cd /var/log/httpd/
-bash: cd: /var/log/httpd/: Permission denied
```
ん？パーミッション？、ここで気づきました。root になっていないことに。(;´д｀)トホホ。

##以下で解決
```
[ec2-user@ip-172-31-23-3 html]$ sudo su
[root@ip-172-31-23-3 html]# cd /var/log/httpd/
[root@ip-172-31-23-3 httpd]# ls
access_log  error_log  modsec_audit.log  modsec_debug.log
[root@ip-172-31-23-3 httpd]# ls -lrt
total 20
-rw-r----- 1 root root    0 Jan 29 16:40 modsec_debug.log
-rw-r----- 1 root root 2544 Jan 29 16:53 modsec_audit.log
-rw-r--r-- 1 root root 5039 Jan 29 16:53 access_log
-rw-r--r-- 1 root root 7672 Jan 29 16:55 error_log
[root@ip-172-31-23-3 httpd]# systemctl restart httpd
[root@ip-172-31-23-3 httpd]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since Sat 2022-01-29 23:47:52 UTC; 11s ago
     Docs: man:httpd.service(8)
 Main PID: 3333 (httpd)
   Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec:   0 B/sec"
   CGroup: /system.slice/httpd.service
           tq3333 /usr/sbin/httpd -DFOREGROUND
           tq3334 /usr/sbin/httpd -DFOREGROUND
           tq3335 /usr/sbin/httpd -DFOREGROUND
           tq3336 /usr/sbin/httpd -DFOREGROUND
           tq3337 /usr/sbin/httpd -DFOREGROUND
           mq3338 /usr/sbin/httpd -DFOREGROUND

Jan 29 23:47:52 ip-172-31-23-3.ec2.internal systemd[1]: Starting The Apache HTTP Server...
Jan 29 23:47:52 ip-172-31-23-3.ec2.internal systemd[1]: Started The Apache HTTP Server.
[root@ip-172-31-23-3 httpd]#
```
#おわりに
あまりお役に立てる記事ではないかも知れません。では、また。
paiza PHP 指定範囲の大文字化

paizaの問題集を毎日解いているのでそこでの学習内容を書いていこうと思います。
回答とは違う手順だったので参考にするくらいにしてもらえると嬉しいです。

####問題
与えられた文字列のなかで指定された範囲を大文字にする。

paizaの場合、標準入力からの値の取得をしないといけないのですが今回は下記のようにしました。

```
$s = "It's nice to meet you."; //与えられた文字列
$a = 6; //始まりの番数
$b = 11; //終わりの番数
```

次に文字列の数だけ処理を回したいので、文字数を数えます。
大文字に変更後の文字列を入れるために空の変数を用意します。
文字列を一文字づつの配列にします。

```
$n = mb_strlen($s);// 出力：22
$ans = "";
$array_s = str_split($s);//文字列を一文字づつ格納
```

次に繰り返し処理を行っていきます。

```
for($i = 0; $i < $n; $i++)//文字の数だけ繰り返す
{
    if($a - 1 <= $i && $i < $b)//何番目から何番目なら
    {
        $ans = strtoupper($s[$i]);//大文字にする
    }else//それ以外なら
    {
        $ans = $s[$i];//そのままにする
    }

    echo $ans;//出力：It's NICE To meet you.
}
```

これで指定された範囲の大文字化ができました。

paizaの問題集はひとつづつクリアしていくと解けるようになっているのでかなり勉強になります。
AndroidのMediastoreで画像を日付順にソートする

スマホを買い替えてAndroid11になった。すると、Android6の時に自作した画像閲覧アプリで、画像をうまく表示できないことがわかった。そのアプリでは、スマホの中の画像を日付順にソートするのに、[ContentResolver](https://developer.android.com/training/data-storage/shared/media?hl=ja)で、MediaStore.MediaColumns.DATE_TAKENを指定してソートしていた。つまり、

```
String sortOrder = MediaStore.MediaColumns.DATE_TAKEN;
```

という感じである。<br>
調べてみると、いつの頃からかDATE_TAKENはAPI level29から追加されたことになり、古いAndroidでは使えなくなったらしい。歴史改変というやつですね。
ただ、悪いことばかりではなく、以前のDATE_TAKENは撮影日付という名称にも関わらず、ファイルの更新日付で決まっていたものが、Exifを読むように変わったらしい。しかし、[Exifから決められないものはNULL](https://issuetracker.google.com/issues/140250785 "[Android Q Beta] Media Store insert DATE_TAKEN is always null")になっており、一筋縄ではいかない。更に、やっかいなことに、[DATE_TAKENはmillisecondsなのに、代わりに使えそうなDATE_MODIFIEDやDATE_ADDEDは秒単位だ](https://zenn.dev/tsutou/articles/59fbb5e71b2988#%E8%AA%B2%E9%A1%8C "Android10からMediaStore#DATE_TAKENがnull になる事がある")という。<br>
諦めてDATE_MODIFIEDでソートするという手もあるが、SQLのCASE句を使えば、これを解決できる。こんな感じである。

```
String sortOrder = {
                "CASE WHEN " + MediaStore.Images.ImageColumns.DATE_TAKEN + " is NULL" +
                        " THEN " + MediaStore.Images.ImageColumns.DATE_MODIFIED + " * 1000" +
                " ELSE " + MediaStore.Images.ImageColumns.DATE_TAKEN + " END"};
```

この勢いでカラムの方もCASE句を使えば状況に応じて日時を取得できるので便利なのだが、残念ながら、最近のContentResolverはカラム指定には単純なカラム名しか受け付けないので、こちらはうまくいかない。<br>
ただ、どうもExifのデータがあっても日付順に並んでくれない画像があることがわかった。[リファレンス](https://developer.android.com/reference/android/provider/MediaStore.MediaColumns#DATE_TAKEN)をよく読んでみると、

>信頼のおける決定のためには、ExifInterface#TAG_DATETIME_ORIGINAL と ExifInterface#TAG_OFFSET_TIME_ORIGINAL　が定義されていなくてはならない

ということらしく。２つ揃っていないとダメらしい。もう一つ、DATE_TAKENの値はnon-negativeのはずなのだが、実際にContentResolverで取得してみると、-1となっている画像があって、これは謎である。ご存じの方は教えてほしい。<br>
ちなみに、[CursorのgetLongのリファレンス](https://developer.android.com/reference/android/database/Cursor#getLong(int))をみると、以下のようになっていて、結局よくわからない。

>カラムの値がnullもしくはカラムタイプが整数型でない、もしくは整数値がLong型の範囲外の場合の結果および例外を投げるかどうかは実装で定義される。
Visualize SQL | Find blank numbers in numbers (part 2)

# Beginning
This technique is based on SQL Puzzle and Answers # 9 available seats
It is better with 『SQL Puzzle and Answers』 to read this article.

Because it says the idea of algorithm and
You can check what each quiz is intended for ・・・

This puzzle is to find numbers that are already filled with numbers and blank numbers in table
thinking like occupied seats and open seat in a restaurant.

There are 20 seats in a restaurant, and number of 1,2,3,8,9,10,16,18,19 seats are occupied.
Find the start and the end number of open seats.


# table and data
```SQL:SQL
CREATE TABLE Restaurant(
   seat integer
);

INSERT INTO Restaurant VALUES(1);
INSERT INTO Restaurant VALUES(2);
INSERT INTO Restaurant VALUES(3);
INSERT INTO Restaurant VALUES(8);
INSERT INTO Restaurant VALUES(9);
INSERT INTO Restaurant VALUES(10);
INSERT INTO Restaurant VALUES(16);
INSERT INTO Restaurant VALUES(18);
INSERT INTO Restaurant VALUES(19);
```

# All combinations of occupied seat
```SQL:SQL
-- all combinations
SELECT R1.seat,R2.seat             
FROM Restaurant AS R1      
  INNER JOIN Restaurant AS R2 ON R2.seat > R1.seat   
```

『R2.seat > R1.seat』which is the condition of INNER JOIN exclude combinations below
The bottom one is not necessary | (R1,R2) = (3,2)

|R1|R2|
|---|---|
|2|3|
|3|2|


![rep_4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1242736/41744892-8cc4-2cf3-83d6-b55e196fde60.png)


# Answer SQL
```SQL:SQL
SELECT R1.seat AS start
	  ,(MIN(R2.seat)-1) AS fin2
FROM Restaurant AS R1
  INNER JOIN Restaurant AS R2 ON R2.seat > R1.seat
GROUP BY R1.seat
HAVING (R1.seat + 1) < MIN(R2.seat)  
```

|start|fin2|
|---|---|
|4|7|
|11|15|
|17|17|

# check SQL in detail
■ step1
R1.seat is unique number because of GROUP BY 『R1.seat』
The nearest seat from R1.seat is fin1. Check above image of『fin1』(red)
　⇒　MIN(R2.seat)

■ step2
R1.seat is occupied one, the next seat which is 『 R1.seat + 1 』 would be the start number
of open seat. 『start』 is either occupied or open.

『fin1』 is occupied one, the previous seat which is 『 MIN(R2.seat) - 1 』would be the end
number of open seat. 『fin2 』 is either occupied or open.

open seats are between 『start』 and 『fin2』but `『start』 and 『fin2』 are `
`either occupied or open. So that needed to select open one.`
Add HAVING condition at step3 to select open one.


■ step3
You can get the start and end of open seat number by adding a condition 
that  『start』 is less than 『fin1』in HAVING condition
The start number can never be greater than the end number


![rep_8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1242736/825c1b66-799e-fc5f-6752-2231eca3e70c.png)


# References
[Joe Celko's SQL Puzzles and Answers](https://www.amazon.com/Puzzles-Answers-Kaufmann-Management-Systems/dp/0123735963)
【初心者向け】ローコード開発／ノーコード開発　～「ソースを書かない手法」の発展

##`はじめに`
従来のシステム開発においても、
GUI（グラフィカル・ユーザー・インターフェース）による直感的な操作で
コーディングを行いプログラムを生成するといった
従来の「プログラミング言語を用いてソースコードを書く」という形式にとらわれない
プラットフォームが普及している。

ローコード開発／ノーコード開発は上記の手法から発展したものとして、
IT業界に留まらず、昨今の世界情勢に伴いIT化を推進したい他業界からの関心が高まっている。

#■ローコード／ノーコード開発とは
##`「ソースを書かない開発手法」の発展`
ローコード／ノーコード開発とは
プログラミングのみに収まらず基本的なシステム構築そのものを
画面上でのドラック＆ドロップなどで行う開発手法を指す。

ローコードとノーコードの違いは
ソースコードの記述による拡張性があるかどうかである。
前者は所定のフォーマットに加えてソースコードによる独自ロジックを導入できる機能を持つ。

#■ツールの一例
>PowerApps

https://docs.microsoft.com/ja-jp/powerapps/

Excelの関数を用いたり、PowerPointでプレゼン資料を作るのと同じ感覚で
アプリケーション開発を行うことができるローコード開発ツール。

>Bubble

https://bubble.io/

様々なアプリ開発のために用意されたパーツをドラッグ＆ドロップして、
視覚的・直感的に開発が行えるノーコード開発ツール。

#■LowとNo、主流はLow？
##`「ソースを書かなくてもよい」からこその欠点`
直感的な操作によるプログラミングで
システム開発における人員・工数負担を削減できる両ツールだが、
ノーコード開発についてはプログラミング言語を使ったコーディングを行う開発と比較すると自由度が低いという欠点が存在する。

実装可能な機能が提供元から限定されているため、
実際にリリースしてから「もっとこんなことがやりたい」という品質向上が実現できずに
手詰まりになる可能性もある。

ゆえに、最低限の開発フォーマットが提供されたうえで、
独自の拡張性を両立しているローコード開発ツールが
今後のシステム開発の負担軽減における主流になると考えられている。


なんにせよ、開発ツールの普及によるプログラミングの低敷居化によって
われわれエンジニアがお役御免になるかというと、
そういう訳でもなさそうなのは安心だ。

#■参考文献
https://persol-tech-s.co.jp/hatalabo/it_engineer/524.html

https://bolt-dev.net/posts/1143
git pushしたファイルをローカルに残しつつgit管理から外したい

タイトル通り、git pushしたファイルを「git管理から外したい、でもローカルには残したい」場合の手順です。

再現手順も掲載しています。
挙動を深掘りしたい場合はご自分で検証してみてください！

# これだけでOK

手短に実行コマンドのみ紹介します。

## ファイル構成
ファイルは両方とも一度コミットされた状態です。
``test2.txt``をgit管理から除外します。

```bash
$ tree
.
├── test1.txt
└── test2.txt
```

## .gitignoreの作成

```bash
$ echo "test2.txt" >> .gitignore
```

## ローカルに残しつつgit管理から除外

```bash
$ git rm --cached test2.txt
```

## コミット

```bash
$ git add .
$ git commit -m "test2 ignore"
```

## プッシュ

```bash
$ git push
```

## 実行結果
ローカルではtest2.txtのファイル自体は残りますが、git管理から除外された状態になります。
リモートリポジトリ上では削除されます。

# 再現手順

上記コマンドの再現手順です。
実際に自分で操作してみると理解が深まります！

コマンドの詳細も説明しています。

## GitHubで実行
リモートリポジトリ``gitignore_test``を作成します。

[リポジトリを作成する](https://docs.github.com/ja/get-started/quickstart/create-a-repo)

## ローカルで実行

### 事前準備
ファイルを作成します。

```bash
$ mkdir gitignore_test
$ cd gitignore_test
$ echo "test1" >> test1.txt
$ echo "test2" >> test2.txt
```

リポジトリを作成します。

```bash
$ git init
```

一度コミットします。

```bash
$ git add .
$ git commit -m "test1 test2 create"
```

デフォルトブランチの名前が``master``の場合は``main``へリネームします。

```bash
$ git branch -M main
```

リモートリポジトリを設定します。

```bash
$ git remote add origin [git@github.com](mailto:git@github.com):*****/gitignore_test.git
```

プッシュします。

```bash
$ git push -u origin main
```
### .gitignoreの作成

```bash
$ echo "test2.txt" >> .gitignore
```

### ローカルに残しつつgit管理から除外
test2.txtをgit管理から除外します。
``cachedオプション``でローカルにファイルを残したままgit管理から除外することができます。

```bash
$ git rm --cached test2.txt
```

コマンド実行後、test2.txtはインデックスに登録されます。

```bash
$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	deleted:    test2.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.gitignore
```

この時点でtest2.txtがgit管理から除外されていることが確認できます。

```bash
$ git ls-files
test1.txt
```

### コミット

.gitignoreの作成とtest2.txtの除外コミットは同時に実行したいので、.gitignoreもインデックスに登録しコミット対象に含めます。

```bash
$ git add .
```

コミットします。

```bash
$ git commit -m "test2 ignore"
[main acbb8df] test2 ignore
 2 files changed, 1 insertion(+), 1 deletion(-)
 create mode 100644 .gitignore
 delete mode 100644 test2.txt
```

### プッシュ

```bash
$ git push
```

# git rm --cachedの注意点

``git rm --cached``を実行した状態つまり「特定のファイルをローカルに残しつつgit管理から外した」状態は、コマンドを実行した環境にのみ適用されます。
そのため、複数人でリポジトリを管理している場合は注意が必要です。

- git rm --cachedを実行した環境
対象ファイルがgit管理から除外されるが、ファイル自体はローカルに残る。

- それ以外の環境
上記の環境で実行されたコミットをgit pullするだけなので、ローカルの対象ファイルが削除される。

自分一人で管理するリポジトリであれば問題ありません。

しかし、チーム開発の場合は各メンバーの環境が異なると動作確認に支障が生じます。開発途中で「特定のファイルをローカルに残しつつgit管理から外す」運用は慎重に行うべきかと思います。

# 参考資料

- [gitの管理対象から特定のファイル、ディレクトリを削除する](https://qiita.com/ytkt/items/a2afd6be8e4f06c1ea25)

# 採用PR
弊社で一緒に働く仲間を募集しています。
全てのオタクを幸せにしたい方、是非ご覧ください！

https://hrmos.co/pages/vivion/jobs/0000191
.prettierrcをymlで書く

# はじめに
コードの見た目を整えるためのPrettierの設定ファイルをYAML形式で書いてみたかったので、備忘録として残しておく。

# 設定項目
公式ドキュメントを参照しつつ、Prettierの設定項目を表形式でまとめる。

https://prettier.io/docs/en/options.html

|項目名|デフォルト値|概要|
|:--|:--|:--|
|printWidth|80|1行の長さ。この設定値を超えると改行される。|
|tabWidth|2|インデントレベルごとのスペース数。|
|useTabs|false|スペースではなくタブで行をインデントする。|
|semi|true|文の末尾にセミコロンを追加する。|
|singleQuote|false|文字列をシングルクォートで囲むかどうか。JSXはこのオプションを無視する。|
|jsxSingleQuote|false|↑ のJSX版。|
|trailingComma|"es5"|複数行のカンマ区切り構文構造における末尾のカンマ表示。<br><ul><li>"es5": ES5(オブジェクトや配列)で有効なカンマを追加する</li><li>"none": 末尾にカンマを追加しない</li><li>"all": 関数のパラメータや呼び出しを含み、可能な限り末尾にカンマを追加する</li></ul>|
|bracketSpacing|true|オブジェクトリテラルに含まれるカッコのスペースを追加。<br><ul><li>true: { foo: bar }</li><li>false: {foo: bar}</li></ul>|
|bracketSameLine|false|複数行に渡るHTML要素の`>`を最終行の最後に置くか、その次の行に単独で置くか。|
|arrowParens|"always"|アロー関数の引数が一つの場合、括弧で囲むかどうか。<br><ul><li>"always": (x) => x</li><li>"avoid": x => x</li></ul>|
|requirePragma|false|ファイルの先頭にプラグマと呼ばれる特別なコメントを含むファイルのみをフォーマットするよう制限することができる。大規模な未フォーマットのコードを徐々にPrettierでフォーマットしていく際に有効。|

# Playground
Prettierの公式サイトでは、どのようにコードをフォーマットできるか、各項目を設定して試すことができるのでオススメです。
![playground.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1504894/400e909d-0b31-8b7f-e161-d5f3c9beb410.png)

https://prettier.io/playground/

# 設定ファイル

自分の場合、以下のような設定ファイルにしました。
YAMLだと文字列はクォートで囲っても囲わなくてもいいため、今回は囲っていません。

```yaml:.prettierrc.yml
arrowParens: always
bracketSameLine: false
bracketSpacing: true
jsxSingleQuote: true
printWidth: 80
requirePragma: true
semi: true
singleQuote: true
tabWidth: 2
trailingComma: all
useTabs: false
```

JSONだと以下です。

```json:prettierrc.json
{
  "arrowParens": "always",
  "bracketSameLine": false,
  "bracketSpacing": true,
  "jsxSingleQuote": true,
  "printWidth": 80,
  "requirePragma": true,
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "all",
  "useTabs": false,
}
```

# 実行

まだフォーマットされていないファイルを調べたい場合には、`--check`オプションを使い、

```shell:ターミナル
% npx prettier --check .
Checking formatting...
[warn] hoge.js
[warn] bar.json
[warn] ...
```

実際にフォーマットを実行する場合には、`--write`オプションを使う。

```shell:ターミナル
% npx prettier --write src/components/Hoge/index.tsx
```

`requirePragma: true`にした場合は、ファイルの先頭に

```typescript
/**
 * @prettier
 */
```

を付けないと整形してくれません。

VSCodeでファイル保存時に整形する場合は、以下のように、`Default Formatter`をPrettierに設定した上で、
![vscode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1504894/2632defb-4202-c749-df8f-589c21c0daac.png)
`Format On Save`を有効にする必要があります。
![vscode_format-on-save.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1504894/fc180c0b-3453-5224-acad-e93bfaf8d513.png)


以上です。間違い等あればご指摘いただけると嬉しいです!
Java環境を作成しGitに登録する

# 概要
備忘録的に、プロジェクトを作成してGitに登録する手順を記載します

# 手順
## ローカルでプロジェクトを作成
以下一例として、mavenでプロジェクトを作成しています

1. PJを作成(方法含めて任意)  
1. `.gitignore`ファイルを配置   
PJフォルダ直下に配置  
自動で作成されるファイル等成果物対象でないものを対象外にする
<details><summary>ファイル例</summary><div>

```
# Java(Javaの自動生成ファイルを対象外にする)
*.class
*.jar
*.war
*.ear

# Eclipse(Eclipseの自動生成ファイル/制御ファイルを対象外にする)
.project
.classpath
.settings

# Idea(Ideaの自動生成ファイル/制御ファイルを対象外を対象外にする)
.idea
*.iml
*.iws
*.ipr

# OS(OSで自動で作成されるファイルを対象外にする)
Thumbs.db
.DS_Store

# Gradle(Gradleで自動作成されるファイルを対象外にする)
.gradle
!gradle-wrapper.jar

# Maven
target

# Build
out
build
bin

# Other
*.log
*.swp
*.bak
```
</div></details>

## gitの設定(ローカル)
以下順にコマンドを実行  
実行する際のカレントディレクトリはPJフォルダ直下  

1. `git init`
1. `git add`
1. `git commit -m "初期コミット"`  
初期コミットの内容は状況に応じて変更
1. `git remote add origin https://xxxxxxx/xxxxx.git`  
GitHubの例  
https://github.com/your-name/project-name.git
1. `git push -u origin master`  
ローカルのプロジェクトをサーバにPush(アップロード)
JavaScriptのコールスタックと挙動の確認方法

どうも。前回の記事で、月に1度更新できたらいいな〜とか言ってて早々に更新し始めました、maruquiです。

今回はJavaScriptのコールスタックについてと挙動の確認についてメモしておきます。

まだまだ技術の経験値が少ないこともあり、ベテランの方から見たら意味が違うような発言をしてしまうかもしれませんが、あたたかく見守ってください。

## コールスタックとは

簡単にいうと、どの関数がどの順番で呼び出されているのかを保存しておく仕組みのことです。文字で説明するだけじゃ意味不明だと思うので、コードで。

```JavaScript:コールスタック

function a() {
    console.log('a is first.');
}

function b() {
    a();
    console.log('b is second.');
    d();
}

function c() {
    b();
}

function d() {
    console.log('d is last.');
}

c();

// 実行結果
// a is first. → b is second. → d is last.
```

実行される順番としては、グローバルコンテキスト → c(); → b(); → a(); → console.log('b is second.'); → d(); になります。

グローバルコンテキストは今回のコードに記載がありませんが、JavaScriptがコードを実行する際に最初に生成するものです。

このように、どの関数がどの順番で呼び出されていくかを保存する仕組みがコールスタックと言います。

ブラウザでも確認ができるので、確認していきます。

## コールスタックをブラウザで確認する

chromeの場合でお話します。他のブラウザは…頑張ってググってみてください。

検証を開いてsourcesをクリック。jsのファイル内で該当の処理にbreakpointを置いてみましょう。画像ではc(); にbreakpointを置いています。

そして、step into next function callを押して行けば辿ってきた処理を確認することができます。画像で「これ」と案内している箇所です。

![callstack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519177/5eddb7a2-005b-a508-632b-7714ef1a00e2.png)

これでJavaScriptの処理の順番がどのように実行されているのかがわかるようになりました。他人が書いたJavaScriptの処理などで勉強が捗ることでしょう。

## まとめ

今回はUdemyの学習記録として、JavaScriptのコールスタックについてまとめました。

参考にした講座はすでに1周していたのですが、当時全く意味不明なままとりあえず進めていたので、2周目に入っています。

このチャプターだけはメモに残しておきたかったので、講座を参考にして記事にしました（丸パクリはしてません）。

またメモしておきたいものが出てきたら記事にしていきます。最後までご覧いただき、ありがとうございました。

## 参考

* 【JS】ガチで学びたい人のJavaScriptメカニズム｜Udemy
<https://www.udemy.com/course/javascript-essence/>

* コールスタックってなに？【JavaScript】｜キノコが何か作るブログ
<https://www.mizukinoko.com/entry/2020/04/21/182048>
GoogleChromeの拡張機能を使って、ブラウザ上の操作を記録してみた


# 目的
> チーム内での共有や、自身の理解目的として

# 以下試したこと

1. Screen Recorder for Google Chror
[https://chrome.google.com/webstore/detail/screen-recorder-for-googl/eclbecdgdoahkliaijlpkigldlkojjdn?hl=ja](https://chrome.google.com/webstore/detail/screen-recorder-for-googl/eclbecdgdoahkliaijlpkigldlkojjdn?hl=ja)

2. Loom -Free Screen and Cam Recorder
[https://chrome.google.com/webstore/detail/loom-%E2%80%93-free-screen-and-ca/liecbddmkiiihnedobmlmillhodjkdmb/related?hl=ja](https://chrome.google.com/webstore/detail/loom-%E2%80%93-free-screen-and-ca/liecbddmkiiihnedobmlmillhodjkdmb/related?hl=ja)

#1ついて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/7021f655-3a2e-89e6-87bb-096a6ddbf33f.png)
1. *[GofullPage](https://chrome.google.com/webstore/detail/gofullpage-full-page-scre/fdpohaocaechififmbbbbbknoalclacl?hl=ja)* の拡張機能と同じように、手順としてを動画(システム音のみ(オンオフ可))にまとめられる。
2. *Qiita*や*GithubPage*のようなホスティングサービス系にアップする際は、gifへ変換しないと使えない。

イメージ図
![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/f6fabb73-8bdd-43ae-da90-0275c51206ac.gif)


#2について
・PC画面上を会話と共に気軽に共有できる。
・調べてみると以前は完全無制限で無料だったが、今は5分以内25動画までが無料範囲とのこと
・トライアル終了日に通知が来て、継続意思ない場合は、無料版に落ちる
・月$8で、上記の制限から外される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/e9c5ca51-3019-b69c-8f9a-1aecb98a61b0.png)

・テレワーク時代なので、チーム内で作業の手順を共有し合うのであれば便利そう。ただし、1つのワークスペースに付き(月$10)とのこと。14日間はトライアル期間。あとは自社や現場に提案次第...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57249/db150ca8-fa44-b01a-482f-5890e1286517.png)

# 総括
> どちらにしても、使い勝手は良さそう。まずは、実践してみて作業してみましょう。
【ASP.NET】「リソースが見つかりません」のエラー原因と対応

# はじめに
同僚がデータ修正ツールを作成することになり、サンプル的に久しぶりに ASP.NET(C#) + MVC + PostgreSQL でテキストボックスにSQLを入力してボタンをクリックすれば、SQLの結果をグリッド(Handsontable)に表示させるだけのアプリケーションを作成したのですが、POSTした際に「リソースが見つかりません」のエラーで嵌りました。

# 現象
テキストボックスにSQLを入力してボタンをクリックすると、最初はSQLの結果がグリッド(Handsontable)に表示されるし、C#の部分にブレークポイントすればデバッグできるのですが、2回目以降になると「リソースが見つかりません」の例外エラーとなり、エラー詳細としては「GetSQLDataのコントローラーが見つからないか、IControllerを実装していません。」となります。

`GetSQLData`というのは、今回MVCのコントローラーで独自に作成したメソッドになります。

ネット検索の対応でも解決できず、メソッド名を`GetSQLData2`とか`GetSQLData3`のように名前を変更すると、デバッグでトレースできて表示までできるのですが、やはり2回目以降になると「リソースが見つかりません」のままです。

* [asp.net VisualStudio でデバッグしようとしたら「リソースが見つかりませんでした。」になる](https://qiita.com/Kakimoty_Field/items/03f874de7770ee7fa2fb)


```csharp:HomeController.cs
public class HomeController : Controller
{
    // GET: Home
    public ActionResult Index()
    {
        @ViewBag.MsgErrCommException = "通信エラーが発生しました。";

        return View();
    }

    /// <summary>
    // SQL文の実行結果を取得する
    /// </summary>
    /// <returns>結果</returns>
    [HttpPost]
    public JsonResult GetSQLData(SendSQLPostViewDataModels data)
    {
        object result = new { success = false, message = "", resultData = "" };
        try
        {
            ListViewModel vm = new ListViewModel();

            ResultData resultData = vm.GetResultData(data.SQL);
            result = new { success = true, message = "Success", resultData = resultData };
        }
        catch (Exception ex)
        {
            result = new { success = false, message = ex.Message, resultData = "" };
        }

        return Json(result, JsonRequestBehavior.AllowGet);
    }
}
```

```javascript:index.cshtml
function preview() {
    let that = this;
    let param = {
        FactryList: null,
        SQL: $("#txtSQL").val(),
    };
    let process = function (data) {
        if (data.success) {
            hot.loadData(data.resultData.Data);
            hot.updateSettings({
                colHeaders: data.resultData.Header
            });
        }
    }
    postAjax('GetSQLData', JSON.stringify(param), process);
}

// PUT用非同期処理
function postAjax(method, data, callback) {
    jQuery.ajax({
        url: method,
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json; charset=utf-8',
        data: data,
        async: true,
        processData: false,
        cache: false
    }).fail(function (xhr, status, error) {
        let msg = '@ViewBag.MsgErrCommException' + '\n' + xhr.status + ' ' + error;
        alert(xhr.responseText);
    }).done(function (data) {
        if (data.success)
            callback(data);
        else
            alert(data.message);
    });
}
```

# 対応
「GetSQLDataのコントローラーが見つからないか、IControllerを実装していません。」というエラーに着目、もしやURLの指定が間違っているのではないかと思い直し下記のように修正してみました。

```javascript:index.cshtml
postAjax('GetSQLData', JSON.stringify(param), process);
            ↓
postAjax('/Home/GetSQLData', JSON.stringify(param), process);
```

結果は正解でした。
これにより、2回目以降でも問題なく動作するようになりました。

# 原因
対応から原因を探れば、URLの指定が間違っていたことになります。Home/Index.cshtml から実行したので、`/Home/`の指定は不要だとおもったわけです。
しかも、最初だけは正しく動くのですから記載が間違っているとは気が付き難いですよね。

# 最後に
これもキャッシュのようなものなんでしょうか、Visual Studio上で最初だけは動くからといって正しいと思うのは間違いのもと。ハマりましたね。
Git Flowでnon-fast-forwardでマージする

## はじめに
私は普段、SourceTreeでGit Flowを使っていますが、Featureブランチを完了時にマージはデフォルトでファストフォワードになっています。
SourceTreeでGitの設定を`マージ時にファストフォワードせずに、常に新規コミットを作成する`にチェックを入れても、ファストフォワードになってしまいます。
そこで今回はGit FlowでFeatureを完了するときにノンファストフォワードでマージする方法を紹介します。


## `.gitconfig`に追加する
`git config`コマンドで.gitconfigにno-ffを追加します。

```bash
git config --global --add gitflow.feature.finish.no-ff true
```

```ini:.gitconfig
[gitflow "feature.finish"]
no-ff = true
```
通常のマージの

```ini:.gitconfig
[merge]
ff = false
```
とは値が逆になっていますので気を付けてください。
【Google colab】argparseでエラーが出た場合の対処法

## 環境
Google Colaboratory


## 現象
以下のコードを Google colab で実行すると、次のようなエラーが出る

```py:Python
import argparse

parser = argparse.ArgumentParser(description="argparse test")
parser.add_argument('-me', '-max_epoch', type=int, default=200)
parser.add_argument('-ms', '-minibatch_size', type=int, default=256)
parser.add_argument('-g', '-gpu', type=int, default=-1)
parser.add_argument('-path', default='./')
args = parser.parse_args()

print(args)
```

```:出力
usage: ipykernel_launcher.py [-h] [-me ME] [-ms MS] [-g G] [-path PATH]
ipykernel_launcher.py: error: unrecognized arguments: -f /root/.local/share/jupyter/runtime/kernel-d19b24d6-a0cd-4fbc-9299-7feb199b5ddc.json
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2
```

## 対処法
上のコードで `args = parser.parse_args()` を `args = parser.parse_args(args=[])` に変えるとエラーが消える

```:出力
Namespace(g=-1, me=200, ms=256, path='./')
```

これで `args.xx` が使えるようになる

## 参考
https://stackoverflow.com/questions/45823991/argparse-in-ipython-notebook-unrecognized-arguments-f
JavaScript/TypeScriptの即時関数と同じことをC++のラムダ式で実現する

# 概要

JavaScript/TypeScriptでは，変数のスコープの可能な限り小さくしてスコープ汚染を防ぐために，以下のような即時関数（関数を定義すると同時に実行する）がよく用いられます．

```ts
const s: string = (() => {
  let ss = ""
  // 一時的な変数ssを使った処理
  return ss
})() // ()をつけてアロー関数を即実行する

// 以降，スコープ外の一時的な変数にはアクセスできない．また，文字列sはconstなので誤って変更される恐れはない．
```

C++（C++11以降）でもラムダ式を用いることで同じこと（関数を定義すると同時に実行する）ができます．具体的には，ラムダ式の処理内容を記述する`{}`の直後にラムダ式を実行する`()`を挿入することである．こうすることで宣言したラムダ式をその場で実行することができます．

注意点として，JavaScript/TypeScriptと異なりC++では変数が自動キャプチャされません．C++ではラムダ式の`[]`においてラムダ式内で使用する変数を明示的にキャプチャする必要があります．

# ソースコード

```cpp
#include <iostream>
#include <sstream>
#include <string>

int main() {
  const std::string& s0 = [/* キャプチャする変数 */]() {
    std::stringstream ss;
    ss << "Lambda expression";  // 一時的な変数を用いた処理
    ss << " ("
       << "Immediately Invoked Function Expression"
       << ")";
    return ss.str();
  }();  // ()をつけてラムダ式を即時実行する
  std::cout << s0 << std::endl;
  // 以降，ラムダ式内で宣言された一時的な変数にはアクセスできない．また，文字列s0はconstなので誤って変更される恐れはない

  return 0;
}

```
adminer 「セッションの期限切れ。ログインし直してください」エラー対処パターンまとめ

#はじめに
adminerで「セッションの期限切れ。ログインし直してください」のエラーをたびたび出くわしたため、対処パターンをまとめました。
パスワードやホスト名、ユーザー名は、正しい前提です。
パターンと言っていますが、基本的に、webサーバーのnginxやapacheのエラーログを確認することが基本になります。


#対処パターン1
シークレットモードにして、「永久的にログイン」をチェックすると、ログインできることがあります。
![スクリーンショット 2022-01-30 11.24.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/7e7f0bbc-906c-e821-3c5f-9ceed68aa1e8.png)

#対処パターン2
セッション情報を保存するディレクトリの所有者が異なり、セッション情報を書き込めないパターンがあります。
webサーバーにnginxやapacheを使用している場合、エラーログを確認すると、以下の`Permission denied`エラーログが出ている場合、その可能性が高いです。

```
Warning: Unknown: open(/var/lib/php/session/~~~~, O_RDWR) 
failed: Permission denied (13) in Unknown on line 0
```

セッション情報の保存先は以下のコマンドで確認できます

```
$ php -i | grep session.save_path
session.save_path =>　"/var/lib/php/session"
```
以下のように`no value`の場合`/etc/php.ini`ファイルを確認するとよいです。

```
$ php -i | grep session.save_path
session.save_path => no value => no value


$ cat /etc/php.ini
php_value session.save_handler "files"
php_value session.save_path    "/var/lib/php/session"
```

sessionディレクトリの所有者を確認し、nginxサーバーの場合、nginxが所有者になっているか確認し、所有者や所有者グループを変更しましょう。
また、chmodコマンドを使用して、権限付与が必要な場合もありますね。

```
$ cd /var/lib/php
$ ls -la session
drwxrwx---  2 root apache    6  1月  30 12:21 session

所有権のグループがapacheになっているため、nginxに変えましょう。

$ chown -R root:nginx session
```

#対処パターン3
私が遭遇したレアケースだと思いますが、EC2のストレージの空き容量が0になったことが原因のときもあります。

エラーログを確認すると、空き容量がないよ、とありました。

```
$ cd /var/log/nginx/
cat error.log
error.log

FastCGI sent in stderr: "PHP message: PHP Warning:  session_regenerate_id(): 
write failed: No space left on device (28)
```
空き容量を確認すると0にでした。

```
$df -h
ファイルシス        サイズ  使用  残り    使用%   マウント位置
devtmpfs         3.8G     0  3.8G    0%   /dev
tmpfs            3.8G     0  3.8G    0%   /dev/shm
/dev/nvme0n1p1    30G   30G   20K  100%   /
```
28GB分のファイルを削除して、再度、adminerにログインすると、エラー内容が変わりました。

```
php_network_getaddresses: getaddrinfo failed: Name or service not known
```

![スクリーンショット 2022-01-26 12.59.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/7d7b7c50-477a-aeb4-576e-e9a5e8222222.png)

容量を再度確認すると、削除したファイルサイズ28GB分が反映されていないことが分かりました。

```
$df -h
ファイルシス        サイズ  使用  残り    使用%   マウント位置
devtmpfs         3.8G     0  3.8G    0%   /dev
tmpfs            3.8G     0  3.8G    0%   /dev/shm
/dev/nvme0n1p1    30G   27G  2.9G  97%   /
```

EC2を再起動すると、空き容量が95%を超え、adminerにログインすることができました。


#参考

https://qiita.com/nissuk/items/2b1aee7f81f351c7ab05#%E3%81%9D%E3%81%AE%E4%BB%96

https://www.adminer.org/
Go言語で外部コマンド実行するときの、標準出力取得するorしない、panicするorしない、の実装まとめ

Go言語で外部コマンド実行するときに、標準出力取得するorしない、panicするorしない、という以下の４パターンを使うので、それぞれの実装をまとめました

1. 外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はpanicする
2. 外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はerrorを返す
3. 外部コマンドを実行し、標準出力を返す。エラーの場合はpanicする
4. 外部コマンドを実行し、標準出力とエラーを返す


## ソース

```golang
package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

func runCommandGetOutputWithoutPanicByArray(command string, args ...string) (string, error) {
	stdout, err := exec.Command(command, args...).CombinedOutput()
	return string(stdout), err
}

func runCommandByArrayWithoutPanic(command string, args ...string) error {
	cmd := exec.Command(command, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

// 1.外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はpanicする
func RunCommand(command string) {
	var tokens = strings.Split(command, " ")
	c := tokens[0]
	args := tokens[1:]
	err := runCommandByArrayWithoutPanic(c, args...)
	if err != nil {
		panic(err)
	}
}

// 2.外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はerrorを返す
func RunCommandWithoutPanic(command string) error {
	var tokens = strings.Split(command, " ")
	c := tokens[0]
	args := tokens[1:]
	return runCommandByArrayWithoutPanic(c, args...)
}

// 3.外部コマンドを実行し、標準出力を返す。エラーの場合はpanicする
func RunCommandGetOutput(command string) string {
	var tokens = strings.Split(command, " ")
	c := tokens[0]
	args := tokens[1:]
	stdout, err := runCommandGetOutputWithoutPanicByArray(c, args...)
	if err != nil {
		panic(err)
	}
	return stdout
}

// 4.外部コマンドを実行し、標準出力とエラーを返す
func RunCommandGetOutputWithoutPanic(command string) (string, error) {
	var tokens = strings.Split(command, " ")
	c := tokens[0]
	args := tokens[1:]
	return runCommandGetOutputWithoutPanicByArray(c, args...)
}

```

## 使い方

```golang
func main() {
	fmt.Println("1.外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はpanicする")
	RunCommand("echo hoge")

	fmt.Println("2.外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はerrorを返す")
	err := RunCommandWithoutPanic("does_not_exist_command")
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("3.外部コマンドを実行し、標準出力を返す。エラーの場合はpanicする")
	stdout := RunCommandGetOutput("echo hoge")
	fmt.Println(stdout)

	fmt.Println("4.外部コマンドを実行し、標準出力とエラーを返す")
	stdout2, err2 := RunCommandGetOutputWithoutPanic("does_not_exist_command")
	if err2 != nil {
		fmt.Println(err2)
	} else {
		fmt.Println(stdout2)
	}
}
```

実行結果

```
1.外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はpanicする
hoge
2.外部コマンドを実行し、標準出力と標準エラーを印字し、エラーの場合はerrorを返す
exec: "does_not_exist_command": executable file not found in $PATH
3.外部コマンドを実行し、標準出力を返す。エラーの場合はpanicする
hoge

4.外部コマンドを実行し、標準出力とエラーを返す
exec: "does_not_exist_command": executable file not found in $PATH
```
HerokuでOpenCVを使う


requirements.txtに入れる

```
 opencv-contrib-python-headless
```

Buildpacksにaptのビルドパックを入れる
![90bb46604c15545fe78348d65fbc7d5d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22270/2579c9aa-eeba-3860-499d-0fafb4e045f4.png)

もしくはコマンドでもオケ

```
heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-apt
```

Aptfileに以下を記載

```
libsm6
libxrender1
libfontconfig1
libice6
```
手順は以下の動画がわかりやすかった
https://www.youtube.com/watch?v=9GCLwYlM8cc
【AndroidStudio】 便利なAuto Import機能でimportの手間をなくす

# Unresolved reference: ○○
このようなエラーはAndroidStudioで開発しているとよく起きますね。
使いたいクラスや機能などをimportしてないことから起きています。

解決方法としてはOption + Enterキーを押すかImportをの箇所をクリックするとimportコードが記載されて突破できます。
今回はその手間をなくす方法の紹介です。

![スクリーンショット 2022-01-30 11.09.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574173/f2be6021-c83f-3d55-89ba-6b0011e7bcd6.png)

# Auto Import機能の追加方法

## Android Studio > Preferencesを開く

ここではAndroidStudioの環境設定をしています。
変えたいことのない設定は多くありますが、設定の変更はここで可能です。

![スクリーンショット 2022-01-30 11.13.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574173/cfa75ced-eec0-6f2d-c27b-68095a7986bb.png)

## 検索欄で「Auto Import」を検索

![スクリーンショット 2022-01-30 11.14.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574173/cc682afe-bace-37ec-97be-eab0e71816e8.png)

## 「Add unambiguous imports on the fly」のチェックをつける

「Add unambiguous imports on the fly」という言葉が意味不明だと思いますが気にしないでください。
直訳で"その場で明確なインポートを追加します"。
行やコードを追加していくことをアプリに許可する際にこれしかないというインポート対象がある場合は自動的にインポートされます。

JavaとKotlinで別れています。環境に合わせてお使いください。
私はどっちも使うので2つともチェックを入れています。


![Cursor_と_Preferences.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574173/d19ee954-fda7-edf8-e790-058677017d8e.png)


## 挙動確認


![スクリーンショット 2022-01-30 11.27.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574173/21e33e2a-16f9-8194-ba24-b8e2421c64af.png)

自動でimport android.widget.ImageViewのコードが追加され、
先ほどまでエラーだった「Unresolved reference: ○○」のエラーが解消されました。

以上になります。
アプリ開発者のツール

私（アプリ開発者）が普段利用しているツール

- [Visual Studio](https://visualstudio.microsoft.com/ja/)
- [Visual Studio Code](https://code.visualstudio.com/)
- [PowerShell](https://docs.microsoft.com/ja-jp/powershell/scripting/overview)
- [Windows Terminal](https://www.microsoft.com/store/productId/9N0DX20HK701)
- [Notepad++](https://notepad-plus-plus.org/)
- [Git for Windows](https://gitforwindows.org/)
- [TortoiseGit](https://tortoisegit.org/)
- [DevToys](https://devtoys.app/)
- [Fiddler Classic](https://www.telerik.com/fiddler/fiddler-classic)

- [Beyond Compare(有償)](https://www.scootersoftware.com/index.php)

## インストール方法（おすすめ）

### インストーラーでインストール

VisualStudioはワークロードの選択するので、基本インストーラーで。

### wingetでインストール

```powershell
winget install Microsoft.VisualStudioCode --override "/MERGETASKS=!runcode,addcontextmenufiles,addcontextmenufolders,associatewithfiles,addtopath"
winget install Microsoft.PowerShell
winget install Microsoft.WindowsTerminal
winget install Notepad++.Notepad++
winget install Git.Git
winget install TortoiseGit.TortoiseGit
winget install Telerik.Fiddler.Classic

winget install ScooterSoftware.BeyondCompare4
```

### Microsoft Storeでインストール

DevToysは[DevToys を入手 - Microsoft Store ja-JP](https://www.microsoft.com/ja-jp/p/devtoys/9pgcv4v3bk4w)からインストール




# Visual Studio Code Extensions

- [Git Graph](https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph) `mhutchie.git-graph`
- [GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) `eamodio.gitlens`
- [PlantUML](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml) `jebbs.plantuml`
- [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) `EditorConfig.EditorConfig`
- [テキスト校正くん](https://marketplace.visualstudio.com/items?itemName=ICS.japanese-proofreading) `ICS.japanese-proofreading`
- [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one) `yzhang.markdown-all-in-one`
- [Excel to Markdown table](https://marketplace.visualstudio.com/items?itemName=csholmq.excel-to-markdown-table) `csholmq.excel-to-markdown-table`
- [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) `ms-dotnettools.csharp`
- [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) `ms-python.python`
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) `dbaeumer.vscode-eslint`

## インストール方法（おすすめ）

```powershell
code --install-extension mhutchie.git-graph
code --install-extension eamodio.gitlens
code --install-extension jebbs.plantuml
code --install-extension EditorConfig.EditorConfig
code --install-extension ICS.japanese-proofreading
code --install-extension yzhang.markdown-all-in-one
code --install-extension ms-dotnettools.csharp
code --install-extension ms-python.python
code --install-extension dbaeumer.vscode-eslint
```
ip netns execでmountエラーが発生する場合の回避策

ChromebookのLinuxで**ip netns exec**するとmountエラーが発生しました。

```linux:
$ cat /etc/debian_version 
11.2
$ 
$ sudo ip netns add host1
$ sudo ip netns exec host1 ip a
mount of /sys failed: Operation not permitted
$
```

以下のコマンドを実行すると回避出来ました。

```linux:
$ sudo mkdir /sys2
$ sudo mount -t sysfs --make-private /sys2
```


```linux:
$ sudo ip netns exec host1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
$ 
```
Security Contextについて

## 始めに

Security Contextとは、個々のコンテナに対するセキュリティ設定のこと。
コンテナ、Podレベルで設定できる。

Dockerでは、以下のように、コンテナの実行に際して、User IDを指定できる。

```
docker run --user=1001 ubuntu(image) sleep 1000
```

それと同じようなことを、k8sで実行できる。

## YAML

```yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: xxxxx
  namespace: default
## User ID 1010で、sleep Commandを実行する。
spec:
  securityContext:
    runAsUser: 1010
  containers:
  - command:
    - sleep
    - "3000"
    image: xxxxx
    name: xxxxx
```

```yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: xxxxx
  namespace: default
spec:
  containers:
  - command:
    - sleep
    - "3500"
    image: xxxxx
    name: xxxxx
## root userとして、SYS_TIMEを実行。
    securityContext:
      capabilities:
        add: ["SYS_TIME"]
```

なお、Podレベルで設定すると、設定はPod内の全てのコンテナに引き継がれる。
Podレベルか、コンテナレベルどちらで設定するかは、
単に、securityContext:をspec:に含めて書くか、spec:containers:の中に書くか、の違いで反映できる。


## 参考

```
https://kubernetes.io/ja/docs/concepts/security/pod-security-standards/
Kubernetes完全ガイド (impress top gear)
https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests/
```

参考にさせていただきました。ありがとうございます。

## 備考
何か間違っている記載ありましたら教えていただけると嬉しいです。