OmniAICreator/Qiita-1.07M huggingface dataset:
ElementUIのFormの自動バリデーション

## コード
```typescript
import { clone, equals } from 'ramda'
import Vue, { PropType } from 'vue'

type Answer = Record<any, any>

const isObject = (item: any): item is Record<any, any> =>
  typeof item === 'object' && item !== null && !Array.isArray(item)

export const AutoValidate = Vue.extend({
  name: 'FormAutoValidator',

  inject: ['elForm'],

  props: {
    valid: {
      type: Boolean,
      required: true,
    },
    answer: {
      type: Object as PropType<Answer>,
      required: true,
    },
    form: {
      type: Object as PropType<any>,
      default(): any {
        return this.elForm
      },
    },
  },

  data: () => ({
    prevAns: {} as Answer,
  }),

  computed: {
    isAnsInitial(): boolean {
      const isInitial = (a: Record<any, any>): boolean =>
        Object.values(a)
          .map(v => (isObject(v) ? isInitial(v) : v === undefined))
          .every(v => v)

      return isInitial(this.answer)
    },
  },

  watch: {
    answer: {
      handler(ans: Answer): void {
        this.validate(() => {
          if (this.form && this.form.clearValidate && typeof this.form.clearValidate === 'function') {
            const differentKeys = this.findDifference(ans, this.prevAns)
            this.form.clearValidate(Object.keys(this.answer).filter(k => !differentKeys.includes(k)))
          }
        })
        this.prevAns = clone(ans)
      },
      deep: true,
      immediate: true,
    },
  },

  methods: {
    validate(cb?: (valid: boolean) => void): void {
      const form = this.form
      if (form) {
        if (form.validate && typeof form.validate === 'function') {
          form.validate((valid: boolean) => {
            const v = !this.isAnsInitial && valid
            if (cb) cb(v)
            this.$emit('update:valid', v)
          })
        }
      } else if (process.env.NODE_ENV === 'development') {
        console.error('This component should be used in el-form or MUST pass form prop')
      }
    },

    findDifference(a1: Answer, a2: Answer): string[] {
      try {
        return Object.keys(a1)
          .map(key => (equals(a1[key], a2[key]) ? '' : key))
          .filter(v => Boolean(v))
      } catch {
        return []
      }
    },
  },

  render() {
    return <div />
  },
})
```

## 使用例
```vue
<template>
  <el-form :model="answer" label-position="top" :rules="rules">
    <auto-validate :valid.sync="valid" :answer="answer" />

    <el-form-item label="Q1. 質問！！" prop="q1">
      <el-select v-model="answer.q1">
        <el-option v-for="({ lavel, value }) in data.q1" :key="value" :label="label" :value="value" />
      </el-select>
    </el-form-item>
  </el-form>
</template>
```

## 簡単な解説
ElementUIのFormは、Vuetifyのそれと違って`v-model`でvalidかどうかを取得できません。それの対処としてのこのコンポーネントです。

`el-form`の子孫では`inject`を使用して`elForm`が受け取れる（少なくともv2.13.2現在）ので、それを利用します。また、フォームの中身の変更の監視は`answer`の`prop`を受け取り、それを監視することで行います。

基本的には、公式docにもあるように`elForm.validate()`を行うことで`valid`かどうかをcallbackで受け取れるので、それを利用します。ただし、これを行うとエラーメッセージが出てとても煩わしいので、それをclearするようなメソッドも作っています。

そのために`ramda`を使用していますが、`clone`を使っているのは`answer`はold valueを`watch`の引数として受け取れない（refなので第2引数と第1引数が同じになる）という理由です。また、`equal`は、deep equalのようなものの実現のために入れています。
Railsチュートリアル学習記録（第１章）

※チュートリアル２周目。開発環境はAtomを使用しています。
※頭の整理と備忘を兼ねて、学習内容を記録しています。
※表現の厳密さや精緻さよりも、直感的に理解しやすいよう記録しています。


・第１章でやりたいこと
⇨開発環境（アプリを作っている場所）で、「Hello World」という文章を表示させるプログラムを作成し、本番環境（アプリを公開する場所）に公開する。


・最初にRailsをダウンロードする。「-v 5.1.6」でバージョンを指定している。バージョン毎に機能が異なったりするので気をつける。

```ruby:filename.rb
$ gem install rails -v 5.1.6
```

・アプリ開発に必要なファイル等を一括ダウンロード（ここでもバージョン指定）

```ruby:filename.rb
$ rails _5.1.6_ new hello_app
```

・実装したい機能に応じてgemfileを修正し、必要なgemをインストール。
※gem：ある機能のソースコードの塊。機能を実装するたびに一からコードを書くのは大変なので、よく使う機能のコードはあらかじめまとまっている。
※gemfile：「このgemは、今このバージョンになっているよ！」といった感じで、gem毎のバージョンが書いてある場所。

```ruby:filename.rb
$ bundle install
```

・アプリケーションとしてデータの出し入れが可能になるよう、仮置きのサーバーを起動。サーバーは開きっぱなしにすることが多いので、サーバー起動を指示する命令は、別ターミナルで打ち込んだ方が良い。

```ruby:filename.rb
$ rails server
```
<http://localhost:3000/>をブラウザで開き、「Yay! You’re on Rails!]
と表示されたらOK。

・このままでは「hello, world!」と表示しないため、少し修正。
・applicationコントローラーで「helloアクション」を定義し、このアクションが呼ばれたら「hello, world」と表示されるよう設定。

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  def hello
    render html: "hello, world!"
  end
end
```

・ブラウザで末尾が「/」のURLがリクエストがされたら、applicationコントローラの「helloアクション」を呼び出すよう設定。

```ruby:config/routes.rb
Rails.application.routes.draw do
  root 'application#hello'
end
```
ここまで終えて、再度<http://localhost:3000/>をブラウザで開く（末尾が「/」のURLをリクエストする）と、「Hello world!」が表示されます。

あとは、ここまでのプログラムを本番環境にアップするだけです。
（以降はチュートリアルの手順通りに粛々と進めるだけなので割愛）
[はてなブログ] fontawesomeをつかう

こんな感じ↓でロケットや外部リンクのアイコンが気軽に使えるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159452/2c08cdb8-bb2f-8521-4e93-f39c13435274.png)


こちらを活用するには、まずfontawesomeのオフィシャルサイトでユーザー登録し、自分用に配布されたURLを確保します。
https://fontawesome.com/

次に、前述のlink同様に、"headに要素を追加"の個所に、

```html:
<script src="https://kit.fontawesome.com/hogehogehoge.js" crossorigin="anonymous"></script>
```

※hogehogehogeに、ご自分のURLを貼り付けてください。

あとは、下記のページからお好きなアイコンを探し、 ```<i class="fas fa-rocket"></i>``` といった具合で、サイドバーや本文に貼り付ければご自由にお使いいただけます。
https://fontawesome.com/icons?d=gallery&m=free

```html:
<p><i class="fas fa-rocket"></i>&nbsp;AIテクノロジー企業「株式会社アジラ」 の<a href="https://jijilla.jp/" target="_blank">DX推進事業本部&nbsp;<em class="fas fa-external-link-square-alt"></em></a>からの製品情報、リサーチレポート、イベント開催をお知らせします。</p>
```

最近ですと、covid-19関連アイコンも追加された模様。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159452/aa5bf369-bbd7-1460-2b5e-5b4127a59849.png)

以上です。
今日のところはこんなところでm(__)m
[Google Spreadsheet] 別シートと同期する

別シートから、データを引っ張ってくるときに `IMPORTRANGE` を使いますね。

こんな感じで使います。A:C列をがぼっと同期します。

```
=importrange("https://docs.google.com/spreadsheets/d/{id}/edit#gid=0","sheetname!A:C")
```

一方、**このセルは同期したいけど、ここはしたくない**みたいなときに、以下を使うと同期元と同じ位置のセルと個別に同期を取ることができて、コピーできるので便利です。

```
=IMPORTRANGE("https://docs.google.com/spreadsheets/d/{id}/edit#gid=0", CONCATENATE("sheetname!",ADDRESS(ROW(),COLUMN())))
```

1. `https://docs.google.com/spreadsheets/d/{id}/edit#gid=0` に コピー元のシートURLを代入
2. `sheetname` にコピー元のシートURLを代入
3. `ADDRESS(ROW(),COLUMN())` は、そこが `A1` のセルなら `$A$1` を動的に返すので、あとはセルのコピーで動的に参照元を参照できる。

おためしあれ。

まだ試してないけどOFFSET使えば、セル位置をズラして参照できそうです。
他にもやり方いろいろあるかもしれないけど、これやったらできたのでシェア。
JavaScriptで空の配列を判別する方法

個人的にすごく詰まったので、メモとして残しておく。

JavaScriptでは条件式の中に比較演算子がない場合、要素によって真偽判定が行われるが、文字列などとは異なり、配列では空の場合でもTrueと判定されてしまう。

```javascript:script
const name_string = ""  //空の文字列
console.log(Boolean(name_string))  //False

const name_list_1 = []  //空の配列
const name_list_2 = [1] //要素のある配列

//配列の要素の有無にかかわらずTrueを返してしまう
console.log(Boolean(name_list_1)) // True
console.log(Boolean(name_list_2)) // True
```

そのため、配列に要素が入っているか判定する場合には、配列の長さを求める.lengthを用いて行う。

```javascript:script
const name_list_1 = []  //空の配列
const name_list_2 = [1] //要素のある配列

//配列が空のときFalseを返すようになった
console.log(Boolean(name_list_1.length)) // False
console.log(Boolean(name_list_2.length)) // True

```
既に生成したインスタンスから作ったAMIでインスタンスを作成する

EC2で作ったインスタンスからAMIを作成し、そのAMIを利用してインスタンスを作ります。

#手順
EC2のインスタンス画面から「アクション」の「イメージ-イメージの作成」を選択します。
イメージの作成で、イメージ名と説明を入力し、「イメージの作成」を押下します。
<img width="769" alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538462/96f01d8e-3eac-6134-b832-18dab11f338e.png">

作成されたら「閉じる」を押下します。
<img width="484" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538462/11c8d6ae-4782-a919-2453-c27bf30a4b7d.png">

これAMIが作成できました。
このAMIを使ってインスタンスを立ち上げます。

EC2からAMIの画面を開きます。
先程作成したAMIを選択し、「起動」を押下します。
<img width="759" alt="3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538462/1658d95f-95cd-d20e-6209-89c422e23671.png">

ここからは普通のインスタンスの作成方法と同じです。
インスタンスの作成は[こちらの過去記事](https://qiita.com/roku28632/items/6a64dab3ea814905230e)にあります。

ここまできたら作成がAMIを使ったインスタンスの作成は完了です。
<img width="791" alt="4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538462/e15d8c8f-b1b8-1088-1208-99cfc5e329d4.png">
Goでリトライ可能エラーと致命的エラーを投げ分けて区別する試み

## やりたいこと

Java系の言語だとtry-catchブロックで例外の種類ごとに例外処理を記述できます。例外が100種類あるんだけど、うち50種類はリトライ可能で、リトライ処理を一括で書きたい場合に以下のように書けるわけです。

```java
try {
  throw new FooException(); // FooExceptionはRetryableExceptionを継承している
} catch (RetryableException e) {
  // リトライ処理
} catch (Exception e) {
  // 致命的エラーなので諦めて死ぬ
}
```

Go初心者の私はGoで同じことをやりたくなったんですが、ピンとくる方法がみつからなかったので試しに実装してみました。

## エラーのwrapと`errors.Is()`を使う方法（Go 1.13以降が必須）

私の実装を紹介します。

```go
package main

import (
	"errors"
	"fmt"
)

var RetryableError = errors.New("Retrying...")

func main() {
	err := Foo()
	if errors.Is(err, RetryableError) {
		// リトライ処理
	} else {
		// 致命的エラーなので諦めて死ぬ
	}
}

func Foo() error {
	return fmt.Errorf("Foo is temporarily unavailable. %w", RetryableError)
}
```

リトライ可能エラーとそれ以外のエラーを区別したい場合に、リトライ可能エラーは必ず`RetryableError`をwrapするようにします。エラーを受け取った側は`errors.Is(err, RetryableError)`でリトライ可能かどうか区別できます。


`RetryableError`のエラーメッセージは単体で見ると意味不明だと思いますが、wrapしたエラーを理解しやすくする意図です。`fmt.Errorf()`の`%w`ではwrap対象のエラーメッセージが展開されますので、`Foo()`が投げるエラーのエラーメッセージは次のようになります。

```
Foo is temporarily unavailable. Retrying...
```

これはログに出すのに便利なので個人的には気に入っています。また、リトライ回数上限に到達したような場合など、`RetryableError`を外すこともできます。

```go
	err := Foo()
	if errors.Is(err, RetryableError) {
		retry--
		if retry >= 0 {
			log.Printf("Ignorable error: %+v\n", err)
			// リトライ処理
		}
		err = fmt.Errorf("%s Gave up.", err.Error()) // RetryableErrorを外す
	}
```

## ご意見募集

正直なところ、これが良い方法なのかはわかっていません。Go上級者の方のご意見をお待ちしております。

## 参考文献

- [Go 1\.13時代のエラー実装者のお作法 \- Qiita](https://qiita.com/shibukawa/items/e633e426a6e67ea2e830)
javascriptとjqueryって何が違うの？

# javascriptとjquery
プログラミングスクールで学んだ事を思い返しているとふと疑問が起こった。

「javascriptとjqueryって何が違うんだ？」

学んだ当初はよく理解出来ていないまま、がむしゃらにコードを書いていたのもあって僕の中で

jquery = javascriptのもう1つの名称

という何ともいい加減な式を頭に思い浮かべたまま卒業まで行ってしまった。

さすがに知識を曖昧なままにしてはいけないと思ったので簡単に説明していく。

まだ未熟なので説明が間違っているかもしれないがご容赦願いたい。

# jquery = javascriptのライブラリ

そもそもライブラリって何だという話だが

ライブラリとは汎用性の高い複数のプログラムを再利用可能な形でひとまとまりにしたものであり

簡単に言うと「jqueryとはjavascriptで開発を行うのを簡単にするものである」

もっと簡単に言えば「jqueryとはjavascriptでよく使う機能や効果のあるコードを簡潔に再編成したものである」



どういうことかと言えばjavascriptで10行くらいコードを記述しなければいけない時に

jqueryを使えば1,2行に短縮できたりする。

つまりとても簡単で便利にjavascriptを使えるのである。

# 注意点
いくら便利だと言ってもjqueryにも弱点はある

1.読み込みが遅くなることがある

jqueryは複数のブラウザで使えるものだが、それゆえいくつものブラウザ判定や分岐が行われている。

つまり本来必要のない処理まで実行してしまっているのでその分動作が重くなってしまうのである。

2.jquery独自の書き方がある

javascriptを簡潔に書き直している形なのでjquery独自の命令文があり

javascriptを使うときにjqueryの記述を行うとエラーが出てしまう事がある。

# それでも便利なjquery
とはいえjqueryは記述が簡単になるのでコードを書くときも見直すときも負担が少なくなり大変便利でなものである。

最初からjqueryを勉強するのもいいがjavascriptを勉強してからの方がもっと体系的に理解できるそうだ。

好きな勉強方法でjqueryを使いこなせるようになろう！
Node.jsに変わるかも？と言われている、Deno 1.0がリリースされたので素振りしてみた。

Deno1.0がリリースされたことで、twitterで界隈で話題になっていたので、素振りしてみた。（メモ程度です）

詳細は公式サイトをご確認ください。
https://deno.land/

まずは、インストール

```
brew install deno
```

これで準備はOK！まずは、「Getting Started」をやってみた。

実行コマンド：　deno run （ファイル名）

```shell
deno run https://deno.land/std/examples/welcome.ts
// => Welcome to Deno 🦕
```


http://localhost:8000/にアクセスすると、「Hello World」が表示される。

```ts:hello_http.ts
import { serve } from "https://deno.land/std@0.50.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}
```

実行はこちら

```shell
deno run --allow-net hello_http.ts
```

「--allow-net」の位置が曲者で最後につけてエラーになり、位置に注意です！
ここtwiiter見てても一度ハマる人が多いようなので。
「--allow-net」はセキュリティの関係で必要みたいです。

今後もウォッチしていこう！
Google maps APIでドラゴンボールのある場所にピンを立てよう！！

# はじめに目次
- Google maps APIの取得
- まずは地図を表示しよう！！
- ピンを立ててみよう！
- 最後に


## Google maps APIの取得
まず取得するには、Googleアカウントとクレジットカードが必要になります。
詳しくはここをご覧になってください。
https://qiita.com/Haruka-Ogawa/items/997401a2edcd20e61037

## まずは地図を表示してみよう！！
APIを取得したら、早速地図を表示してみましょう！
地図を表示するには、HTML,CSS,JavaScriptが必要になります。一応全てをHTMLで書くことができますが、
今後のことを考えて分けて書くようにします。まずはHTMLです。

~~~map.html
<html>
<head>
    <meta charset="UTF-8">
    <title>map</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div id="map"></div>
    <script src="js/map.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>
</body>
</html>
~~~
YOUR_API_KEYのところをあなたが取得したAPIに置き換えましょう！次はJavaScriptです。
今回は私が石垣島出身なので地図の中心の座標は石垣島にしたいと思います。

~~~map.js
var map;
var Center = {lat: 24.4064, lng: 124.1754};
function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
        center: Center,
        zoom: 11.5
    });
}
~~~
JavaScriptで表示するマップの中心座標や拡大サイズなどを変更します。今回はその二つのみ指定していますが、それ以外にもピンを立てる場所やピンに記載する情報、経路の表示などを設定することができます。
次は、cssでmapのサイズを決めていきます。

~~~style.css
body {
    height: 100%;
    width: 100%;
}

#map {
    height: 100%;
    width: 100%;
}

~~~
今回は画面全体をマップにするので縦・横共に100%ととしています。
これでマップを表示する準備が整いました。早速htmlを開いてみましょう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637759/dc0847a5-3afa-538d-aad7-91d36c1ae2d8.png)

このような感じで表示することができます！

## ピンを立ててみよう！
地図が表示できましたがこれではまだ面白くないので、手始めにピンを立ててみましょう。

~~~map.js
var map;
var marker;
var Center = {lat: 24.4064, lng: 124.1754};
function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
        center: Center,
        zoom: 11.5
    });
    marker = new google.maps.Marker({
        position: Center,
        map: map,
        title: "石垣島"
    });
};
~~~

ピンを立てるにはMarkerメソッドを使います。position,地図を表示する場所,markerのタイトルを決めます。今回は中心と同じ座標を使っています。表示してみるとこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637759/4a027774-6ce1-0179-7015-50957f34f44a.png)

無事ピンを立てることができました！

## 最後に
いかがだったでしょうか？私自身初めて地図を表示するときは何度もうまくいかず、あきらめかけたものです。そう言った人が少しでも減るようにこの記事を書きました。また、複数のピンを立てたり、経路の表示の仕方は追々書いていきたいと思います。
参考文献
https://developers.google.com/maps/documentation/javascript/examples/event-simple
Laravel 7 （Laravel10） アプリからメールを送信する

# 目的

- Laravelアプリからのメール送信で非常に詰まったため実施方法をまとめる

# 追記（2023/05/28）

- 別の環境ですが、laravel10の環境でも本方法でtinkerからメールを送れることを確認しました。

# 実施環境

- ハードウェア環境(下記の二つの環境で確認)

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.3) |
| ハードウェア | MacBook Pro (16-inch ,2019) |
| プロセッサ | 2.6 GHz 6コアIntel Core i7 |
| メモリ | 16 GB 2667 MHz DDR4 |
| グラフィックス | AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いて導入 |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いて導入 |

# 前提情報

- Dockerなどを使用せず、直接MacにLaravelの開発環境を構築して作業を行っている。自分の環境の構築方法を下記に記載する。
    - [Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08)
- Gmailを用いたメールの送信を行う。

# 説明後の着地点

- 当該laravelアプリのtinker上からコマンドにより指定したメールアドレスへのメール送信を行うことができる。

# 概要

1. Googleアカウントの取得と設定
1. Laravelアプリ側でのメール設定
1. 確認

# 詳細

1. Googleアカウントの取得と設定
    1. メールを送信するGoogleアカウントを作成する後ログインする。すでに持っているアカウントで送信を行う場合はログインする。
    1. 先にログインしたGoogleアカウントのGmailアドレスとパスワードを記憶しておく。
    1. 下記の方法で安全性の低いアプリのアクセスを有効にする。
        - [Google 安全性の低いアプリのアクセスを有効にする方法](https://qiita.com/miriwo/items/7c5a451a35cecdd72085)
1. Laravelアプリ側でのメール設定
    1. メール送信を実装したいアプリのアプリ名ディレクトリまでターミナルで移動する。
    1. アプリ名ディレクトリで下記コマンドを実行して設定ファイルを開く。

        ```terminal
        $ vi .env
        ```
    1. 開いた設定ファイルの26行目付近に下記の様な記載がある事を確認する。
    
        ```アプリ名ディレクトリ/.env
        MAIL_MAILER=smtp
        MAIL_HOST=smtp.mailtrap.io
        MAIL_PORT=2525
        MAIL_USERNAME=null
        MAIL_PASSWORD=null
        MAIL_ENCRYPTION=null
        MAIL_FROM_ADDRESS=null
        MAIL_FROM_NAME="${APP_NAME}"
        ```
    1. 先の設定ファイルのメールの設定部分を下記の様に修正する。

        ```アプリ名ディレクトリ/.env
        MAIL_DRIVER=smtp
        MAIL_HOST=smtp.gmail.com
        MAIL_PORT=587
        MAIL_USERNAME=安全性の低いアプリのアクセスを有効にしたGoogleアカウントのgmailアドレス
        MAIL_PASSWORD=安全性の低いアプリのアクセスを有効にしたGoogleアカウントのログインパスワード
        MAIL_ENCRYPTION=tls
        MAIL_FROM_ADDRESS=安全性の低いアプリのアクセスを有効にしたGoogleアカウントのgmailアドレス
        MAIL_FROM_NAME=メール差出人の名前(任意のものを入力する)
        ```
    1. 筆者の環境での当該記載の例を下記に記載する。(パスワードのみ伏せる)

        ```
        MAIL_DRIVER=smtp
        MAIL_HOST=smtp.gmail.com
        MAIL_PORT=587
        MAIL_USERNAME=laravel.mail.0104@gmail.com
        MAIL_PASSWORD=*************
        MAIL_ENCRYPTION=tls
        MAIL_FROM_ADDRESS=laravel.mail.0104@gmail.com
        MAIL_FROM_NAME=demo-laravel-crud
        ```
    1. .envファイルを保存して閉じる。
1. 確認
    1. アプリ名ディレクトリにて下記コマンドを実行する。

        ```terminal
        $ php artisan tinker
        ```
    1. tinkerで下記を実行してテストメールを送信する。（下記のそのままコピーして実行してもエラーになる。「テストメール送信先アドレス」には皆さんの環境にあったメールアドレスを入力して実行してください。）

        ```php
        >>> Mail::raw('test mail', function($message) {$message->to('テストメール送信先アドレス')->subject('Test');});
        => null
        ```
    1. テストメール送信先の受信ボックスを確認して下記の様なメールが届いていればメール送信の設定は完了である。(送信元名前と送信元アドレスはみなさんとは異なる)

        <img width="430" alt="Test_-_shun_okawa_gmail_com_-_Gmail.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/69b627d3-e4d4-a34f-ff7d-640c765e3340.png">
洋数字が1桁の時は全角、2桁以上の時は半角にするツール

## 初めに
会社の文章のポリシーで洋数字が1桁の時は全角、2桁以上の時は半角にするというルールがありました。
いちいち手作業で直していると時間の無駄なのでツールを作りました。
## 簡単な仕様
- 洋数字が1桁の時は全角、2桁以上の時は半角
- 数字に挟まれた`,` `.` `:` `/` は半角に変換
- 数字の間に`,` `.` `:` `/`があって２桁以上なら半角
 - (例）1,000、5/5、1:30 などは半角 

## 簡単な設計
- 最初に数字を全て半角にする
- 1桁の数字を全角に変換
 - 前後の数字だけでなく `,` `.` `:` `/` にも注意する
 - 文頭は改行前の値を気にしない
 - 文末も次の段落の頭の文字を気にしない
 - etc...


## ソースコード(javaScript)
#### 初めに変数、hanに半角洋数字を、zenに全角洋数字を代入

 var han = "0123456789";
 var zen = "０１２３４５６７８９";

#### フォームから送られてきた値を変数textに挿入

```
  var text = document.henkan.mytext.value;
```
### 全ての数字を一度半角に変換
#### for文で、変数textの文字数処理を行う
- `text.charAt(i)`で文字を取得
- 上で取得した文字を、indexOfで変数`zen`に格納されている全角数字があるか探す。
- あれば`n = zen.indexOf(c,0);`で変数`zen`の何番目の文字に該当するか調べ変数`n`に代入、なければ`0`を代入
- `if (n >= 0)`で検索しても、あれば、`han.charAt(n);`で変数`han`の何番目かを調べ、それに変換し、変数`c`に代入。
- 変数`c`の値を変数`str`に入れていく

```
  var str = "";
  for (i=0; i<text.length; i++){
    c = text.charAt(i);
    n = zen.indexOf(c,0);
    if (n >= 0){
      c = han.charAt(n);
      str += c;
    }else{
      str += c;
    }
  }
```
####数字に挟まれた`,` `.` `:` `/` は半角に変換
※以下の`(\d+?)●(\d+?)`の●の部分は全角です

```
str = str
  .replace(/(\d+?)／(\d+?)/g, "$1"+"/"+"$2")
  .replace(/(\d+?).(\d+?)/g, "$1"+"."+"$2")
  .replace(/(\d+?),(\d+?)/g, "$1"+","+"$2")
  .replace(/(\d+?)：(\d+?)/g, "$1"+":"+"$2");
```
####１桁の数字は全角に
※以下の`var CONV_TABLE = ["０","１","２","３","４","５","６","７","８","９"];`の洋数字は全角


```
str = str.replace(/(^|(?:[^0-9.,:/]))([0-9])((?![0-9.,:/])|$)/g,
  function(m) {
    var CONV_TABLE = ["０","１","２","３","４","５","６","７","８","９"];
    var s, n;
    if (m.length == 1) {
      s = "";
      n = CONV_TABLE[parseInt(m)];
    } else {
      s = m.charAt(0);
      n = CONV_TABLE[parseInt(m.charAt(1))];
    }
    return s + n;
  });
```

####ユーザーが視覚的に数字の全角半角を確認できるようにする
- 変数`str_chk`を作り、ユーザーが確認できるように一桁洋数字には赤、2桁（記号含む）以上には青色で画面に返す
- 
※以下の2行目の`  str_chk = str_chk.replace(/([０-９]{1})/g, "<span class=\"bkred\">"+"$1"+"</span>");`の洋数字は全角です


```
  str_chk = str
  str_chk = str_chk.replace(/([０-９]{1})/g, "<span class=\"bkred\">"+"$1"+"</span>");
  str_chk = str_chk.replace(/([0-9]+)([.,:/]{1})([0-9]+)([.,:/]{1})([0-9]+)/g, "<span class=\"bkblue\">"+"$1$2$3$4$5"+"</span>");
  str_chk = str_chk.replace(/([0-9]+)([.,:/]{1})([0-9]+)/g, "<span class=\"bkblue\">"+"$1$2$3"+"</span>");
  str_chk = str_chk.replace(/(\d{2,})/g, "<span class=\"bkblue\">"+"$1"+"</span>");
  var text = new String;
  text = '<div style="font-weight:bold;">■<span style="color:red;">１桁</span>の洋数字は<span style="color:red;">赤</span> <span style="color:blue;">２桁以上</span>は<span style="color:blue;">青</span>で表示されます。</div>';
  document.henkan.mytext.value = str;
  str_chk = str_chk.replace(/\r\n|\n/g, '<br>');
  document.getElementById('preview').innerHTML = str_chk;
  document.getElementById('kome').innerHTML = "↓ココをコピーして使って下さい" ;
```
インラインやブロックについて

<h1>displayとは、inlineやblockの違い</h1>
<h3>displayについて</h3>
<ul>
<li>プロパティの一つで、要素の表示形式を決めるもの</li>
<li>displayに対して、表示形式を指定する値が「inline」や「block」である</li>
</ul>
![1589441134568@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634481/689ec655-33e8-a302-a9c8-31f5dc4ab075.jpeg)




![1589445343450@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634481/61e80000-e81e-9464-c632-46c29e7238df.jpeg)

<h3>inlineやblock、inline-blockにはそれぞれ初期設定値が決まっていたり、指定できることとできないことがあります！</h3>
例えばblockは改行されるが、inlineは横並びになる。
inlineは幅や高さの指定ができないため、左右のpaddingとmarginしか指定できない。（widthやheightなどで指定できないということ）
blockはtext-alignの指定ができない（text-alignはまた別の機会に説明）
などなどルールがあるので頭に入れておくように！



<h3>inline-blockとは</h3>
inline-blockとはinlineのように横並びになっているblock。
なので幅や高さを指定することはできる。


<h1>今回新しく知った情報</h1>
<ul>
  <li>「vertical-align」 => text-alignの縦バージョン</li>
  <li>「list-style-type: none;」 => ul要素の箇条書きのボッチを消す</li>
</ul>
json api形式のスネークケースのレスポンスをキャメルケースにする[jsona]

# スネークケースのレスポンスをキャメルケースにしたい

## 背景
フロントエンド側でapiつなぎこみ作業していて、
サーバーからのレスポンスがスネークケースで、
そのままフロント側で使うとeslintエラーになる。。。
そこでスネークケースをキャメルケースに手動で変換する。。。 ← これがめんどい、なんとかしたい

## 対処
こんな感じのレスポンスが来たとする

```
{
  "data": {
    "id": "1",
    "type": "movie",
    "attributes": {
      "name": "test movie",
      "year": null,
      "is_released": true,
      "director_name": "hoge"
    }
  }
}
```

まず、[jsona](https://github.com/olosegres/jsona)というライブラリを使って、扱いやすい形にする

```Javascript
import axios from 'axios'
import Jsona from 'jsona'

const dataFormatter = new Jsona()
const getData = async () => {
    try {
        const response = await axios.get('/data')
        console.log(dataFormatter.deserialize(response))
    } catch (error) {
        console.log(error)
    }
}

// console.logの結果
{
  type: 'movie',
  id: '1',
  name: 'test movie',
  year: null,
  is_released: true, // ここと
  director_name: 'hoge' // ここをキャメルケースにしたい
}

```

[jsonaのオプション](https://github.com/olosegres/jsona#build-process-and-property-names)にいい感じのがある
jsonaの初期化時にオプションとして、SwitchCaseJsonMapperを下のように渡せば良い

```Javascript
import Jsona, { SwitchCaseJsonMapper } from 'jsona

const dataFormatter = new Jsona({
    jsonPropertiesMapper: new SwitchCaseJsonMapper({
        switchChar: '_'
    })
})
```

こうすることで先ほどのconsole.logの結果が、下のようにキャメルケースになる

```
{
  type: 'movie',
  id: '1',
  name: 'test movie',
  year: null,
  isReleased: true,
  directorName: 'hoge'
}
```
よく使うchrome extension

#React Developer tools

#JSON formatter

#Page Ruler Redux

#ColorZilla
ブラウザ上の色を探ってくれる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209211/f79ce36f-2d3b-2037-0ca8-6e4c2be8f7e0.png)
StringUtils#containsAnyメソッドの注意

`org.apache.commons.lang3.StringUtils`クラスの`containsAny`はオーバーロードされたいくつかのメソッドがあるが、ハマりやすい挙動があるため注意。

第2引数が`CharSequence`の

```java
public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) 
```
の方のメソッドは、第2引数の文字列に含まれるいずれかの`文字`が含まれていた場合にtrueとなる。

```java
// 例
StringUtils.containsAny("abcde", "aaa"); // true

StringUtils.containsAny("abcde", "efghi"); // true
```

第2引数が`CharSequence...`の

```java
public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences)
```
の方のメソッドは、第2引数の文字列配列に含まれるいずれかの`文字列`が含まれていた場合にtrueとなる。(今回は、こちらが想定していた挙動)

```java
// 例
StringUtils.containsAny("abcde", "aaa", "bbb", "ccc"); // false

StringUtils.containsAny("abcde", "cde", "def", "efg"); // true
```

可変引数のメソッドなのに、引数の数が`1`のときだけ挙動が変わるメソッド(のように見える)のため、これからバリエーション増えそうだから`StringUtils.contains()`じゃなくて`StringUtils.containsAny()`にしとこうという安易な考えでハマらないように注意。

以下のように無理やりキャストすることで、可変引数のメソッドの方を呼び出すようにできる。

```java
StringUtils.containsAny("abcde", new String[]{"aaa"}); // false

StringUtils.containsAny("abcde", new String[]{"efghi"}); // false
```
[Tips]Pythonで関数をつなげるときの見やすい書き方

この書き方知らなかった&真似しようっと思った書き方を紹介します
データ分析やデータ前処理をする時に関数を何個も実行することあると思いますが下記みたいにカッコをつけることで関数を改行して書くことができます。
これ見やすくなるので好きです。


```python
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()

(
data
.where(data['sepal length (cm)'] > 5)
.where(data['petal length (cm)'] > 5)
.sum()
)
```

以上！
Routing Error[No route matches [GET] “/logout”]エラーと格闘した話



##前提
-**Rails 6.0.3.1**
-**ruby 2.6.3**

***

railsでアプリを作成中にヘッダーにLogoutのリンクを作成していました。

動作確認で、ボタンを押してみると、
あらまあ....

```
No route matches [GET] “/logout”
```

お怒られました....
頼むから、ログアウトさせてくれ...
旅立たせてくれよ...

こうして長いRouting Error[No route matches [GET] “/logout”]エラーとの
戦いが始まるであろうとは、知る由もなかったのである。

***

##やってみたこと

##①ルーティングの確認

*No route matches*って言ってるし、どうせルーティングミスってるんでしょ!!!
ほんまアホやなワイ。

ちゃんとlogout_path使ってるし、HTTP Verb🦆: POSTになってるやんな(汗)。

**ルーティングはあってはるやん**

##②viewでメソッドの指定の確認

次いこ次。飲み足りんし、二軒目にきました。

```
<%= link_to “Log out”, logout_path, method: :post, class: “nav-link text-light”%>
```
**へいらっしゃい!!!!!!!**

と思いきや、お主も合ってはるな。
ちゃんと、postしていますな。

##③検証ツールで確認

ほいなら、次は個室居酒屋で三軒目や。
HTML上で確認や。

```
a class=“nav-link text-light” rel=“nofollow” data-method=“post” href=“/logout”>Log out</a>
```

**fuck　the po00ce!!!!!!!!!**

マジかいな。まだ飲みたらんな!!!!!!!!!!!
**data-method=“post**
postさん、ちゃんといるんか............

##④jQueryがきちんと動いているか確認する

[Boys Be Engineer 非エンジニアよ、エンジニアになれ](https://kurose.me/sorcery-logout-route-matches-get-error/)

このイカした記事で、jQueryに問題あるんちゃう？
っていう新たなる誘い。
四軒目に来ました。

[Rails6でjQueryの導入方法](https://qiita.com/masahisa/items/eaacb0c3b82f4a11fc13)
[Rails 6にjQueryとBootstrapを入れる]
(https://qiita.com/kazutosato/items/d47b7705ee545de4cb1a)
以上の記事で、rails6での導入方法をかたっぱしから試すロドリゲス。


撃沈ロドリゲス.................
ほなもう一軒行こうか......

##⑤environment.jsの一部の記述を削除


```/config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')

environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)
environment.config.resolve.alias = {'vue$': 'vue/dist/vue.esm.js' }

const webpack = require('webpack')
environment.plugins.prepend('Provide',
    new webpack.ProvidePlugin({
        $: 'jquery/src/jquery',
        jQuery: 'jquery/src/jquery'
    })
)
module.exports = environment
```

今の設定。

それをこうしてこう!!!!（語彙力なし）

```/config/webpack/environment.js
const { environment } = require('@rails/webpacker')
#2-7行目をコメントアウト
// const { VueLoaderPlugin } = require('vue-loader')
// const vue = require('./loaders/vue')

// environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
// environment.loaders.prepend('vue', vue)
// environment.config.resolve.alias = {'vue$': 'vue/dist/vue.esm.js' }
#ここまで

const webpack = require('webpack')
environment.plugins.prepend('Provide',
    new webpack.ProvidePlugin({
        $: 'jquery/src/jquery',
        jQuery: 'jquery/src/jquery'
    })
)
module.exports = environment
```

やっと旅立てる........
vue系のイケイケライブラリが邪魔してたらしい。
環境によっては、コメントアウトしなくても解決するっぽい。

**四軒目でわっしょい（jQueryがきちんと動いているか確認する）の記事しかなかったので、わっっしょいできなかった人は、コメントアウトしてみると行けるかもです。

五軒目にして、やっと旅立てる。
**わっしょい!!!!!!**
【Java】同一性と同値性の違い

Yuheiです。

最近Java Silverの学習をしていますが、引き続きわからなかった部分があったので、まとめることにしました。

#同一性について

＝＝演算子を使って比較する。

左辺と右辺が同じオブジェクトであるかを調べます。

例：変数aと変数bが同じオブジェクトであるかを比較

```java:
String a = new String("sample");
String b = new String("sample");
System.out.println(a == b); 
```

上記の結果は、同じオブジェクトなので、「true」と表示されます。


反対に、下記だと、「false」になる。

```java:
String a = new String("sample");
String b = "sample";
System.out.println(a == b); 
```

以上のように、同一性は、変数同士で同じオブジェクトであるかどうかを比較する。

#同値性について

equals演算子を使い、変数内が同じ値(内容)かどうかを比較する。

例：等しい場合

```java
String a = "サンプル";
String b = "サンプル";
System.out.println(a.equals.b);
```
上記は、変数の中身が一致しているので、「true」と表示します。


逆に「false」と表示するときの場合は、

例：等しくない場合

```java
String a = "サンプル";
String b = "サンプル1";
System.out.println(a.equals.b);
```
変数aには、「サンプル」と入っているのに対し、変数bには「サンプル１」と入っています。

このような場合、値の中身は一致しないので、「false」となります。

# まとめ
同一性で調べるのは、オブジェクト。
同値性で調べるのは、変数の中身。

それぞれ調べる内容は違い、使うメソッドや演算子も違います。

以上です。
2020/06/03 プログラミング(フロントエンド)学習4日目 メモ

# 本日の学習範囲
### ドットインストール
・はじめてのCSS #08〜#10
（学習時間：1.5時間）
## CSS学習メモ
### Flexbox
Flexible Box Layout Moduleの略。
ボックスを柔軟にレイアウトできる
### displayプロパティ
`{display: ○○;}`
要素の表示形式を指定する
`{display: flex;}`
で指定した要素の子要素を横並びにする
### border-radiusプロパティ
`{border-radius: 長さor○%}`
ボックスの四つ角の角丸をまとめて指定する
%は指定された要素の幅と高さに基づいたものになる
`{border-radius: 50%}`
の場合、正円になる
### border-styleプロパティ
`{border-style: ○○;}`
ボーダーのスタイルをまとめて指定する
`{border-style: solid;}`
の場合、一本の実線になる
### font-weightプロパティ
`{font-weight: ○○;}`
フォントの太さを指定する
`{font-weight: normal;}`
の場合、通常の太さになる
SQL Serverで文字列をByte数で切り取る

SQL Serverで文字列をByte数で切り取ろうとすると結構大変だった。

# 経緯
他システムから固定長のファイルが送られてくるので、それを利用側（SQL Server 2019）で使いやすいように列を分割しようとしたらハマった。
※[bcp ユーティリティ](https://docs.microsoft.com/ja-jp/sql/tools/bcp-utility?view=sql-server-ver15)を使えばもっと楽にできたのかもしれないが、今回は分け合ってSQLで対応しなければならなかった。

# 結論
断っておくが今回は固定長の為、切り取ろうとしている位置に全角文字(2Byte文字)が来ることはあり得ない。
試していないが全角文字と途中で切ると、1Byte少ない文字列が返ってくるらしい。

record_valueカラムの7Byte目から4Byte切り取る場合

| 元データ       | やりたいこと |
| ---------- | ------ |
| あいうえおかきくけこ | えお  |

```
REVERSE(CONVERT(VARCHAR(4), REVERSE(CONVERT(VARCHAR(10), [record_value]))))
```

# 解説
## Step1
VARCHARにCONVERTする事で[LEFT関数](https://docs.microsoft.com/ja-jp/sql/t-sql/functions/left-transact-sql?view=sql-server-ver15)のByte版になる。

| record_value | CONVERT(VARCHAR(10), [record_value]) |
| ------------ | ------------------------------------ |
| あいうえおかきくけこ   | あいうえお                                |

ここでは必要となる文字列を含んだByte数で区切る。
これで第1段階はクリア。あとは前から余分な文字をそぎ落とす。

## Step2
[REVERSE関数](https://docs.microsoft.com/ja-jp/sql/t-sql/functions/reverse-transact-sql?view=sql-server-ver15)を使えば文字列を反転させる事ができる。

| record_value | REVERSE(CONVERT(VARCHAR(10), [record_value])) |
| ------------ | --------------------------------------------- |
| あいうえおかきくけこ   | おえういあ                                         |

## Step3
Step1とStep2の応用。
取り出したいByte数でVARCHARに変換し、REVERSEで元の文字列を再度反転させる。

| record_value | REVERSE(CONVERT(VARCHAR(4), REVERSE(CONVERT(VARCHAR(10), [record_value])))) |
| ------------ | --------------------------------------------------------------------------- |
| あいうえおかきくけこ   | えお                                                                       |

# 補足
なぜこんな回り道をしなければならないかと言うと、

* [SUBSTRING関数](https://docs.microsoft.com/ja-jp/sql/t-sql/functions/substring-transact-sql?view=sql-server-ver15)が文字数を指定。
* [LEN関数](https://docs.microsoft.com/ja-jp/sql/t-sql/functions/len-transact-sql?view=sql-server-ver15)が末尾の空白を除いた文字数を返してしまう。( **固定長ファイルの操作で致命的** )

といった事があるため。
固定長嫌い。

# 参考サイト
* http://cream-worker.blog.jp/archives/1067499727.html
ViewModel と変更通知プロパティ

## はじめに

オレオレ解釈の覚え書き　その９

一番最初にやるべきだった変更通知プロパティについてまとめます。
タイトルには「ViewModel と～」とありますが、Model 層で使用される場合もあります。

## 本文

MVVM では TextBox.Text や CheckBox.IsChecked 等の依存関係プロパティに、ViewModel で定義された変更通知プロパティをバインドさせることで値を伝播することができます。つまり View の変更を ViewModel へ、ViewModel の変更を View へと、同期を取り合うということです。

今回は ViewModel に定義する変更通知プロパティについて紹介します。これは通常のプロパティ（いわゆる自動実装プロパティ）とは異なり、自身の値の変更を通知する機能を併せ持つプロパティを指します。原始的には INotifyPropertyChanged インターフェースを実装したクラス（これが ViewModel となります）を用意し、プロパティのセッターではバッキングフィールドを確認、値に変更があれば置き換えたうえで INotifyPropertyChanged.PropertyChanged イベントを発生させます。

```cs:ViewModel
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace TestApp.ViewModels
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
            => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        private string _text;
        public string Text
        {
            get => this._text;
            set
            {
                if (this._text != value)
                {
                    this._text = value;
                    this.OnPropertyChanged();
                }
            }
        }
    }
}
```

愚直に実装すると上記のようになりますが、プロパティの部分はともかくとして、変更通知のイベントを自前で処理することは少ないはずです。大半の MVVM フレームワークではこれらの機能を搭載した基底クラスが提供されており、Prism の BindableBase、Livet の NotificationObject、MVVM Light Toolkit の ObservableObject などがそれにあたります。
先の例を Prism を使用して書き換えると次のようになりスッキリします。

```cs:ViewModel
using Prism.Mvvm;

namespace TestApp.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private string _text;
        public string Text
        {
            get => this._text;
            set => this.SetProperty(ref this._text, value);
        }
    }
}
```

なお View はコントロールのプロパティにバインドさせるだけです。Mode で同期の方向を、UpdateSourceTrigger でタイミングを制御することもできます。この辺りの仕様は .NET のリファレンスを確認してください。

```xml:View
<Window x:Class="TestApp.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:p="http://prismlibrary.com/"
        p:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <TextBox Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</Window>
```

## おわりに

今回は View と ViewModel をつなぐ仕組みの中でも、頻出で重要な機構である変更通知プロパティについてでした。
移譲コマンドは処理の移譲だけでしたが、この変更通知プロパティがあることで値を受け渡すことも可能になります。ここまで役者が揃ってくると、多くの処理を MVVM パターン上で構築できることに気づきます。とはいえ、構築できることと楽に実装できることの間には溝があり、正直今回の例にあるようにプロパティのセッターで一々変更を通知するのは面倒です。複数のプロパティの変更通知を絡める処理などが出てくると管理も大変になるでしょう。

次回は、このような変更通知やリアクティブプログラミングを強力にサポートするライブラリである ReactiveProperty について、表面だけサラッとご紹介します。
ITパスポート（本に載ってない）

プロキシサーバ
内部ネットワークからインターネットへのアクセスを中継する装置、または実現するソフトウェアのことです。プロキシサーバを使用することで、高速なアクセスや安全な通信などを確保することができます。

マルチスレッド
マルチ（2つ以上）なスレッド（処理）のことを言います。
処理効率を上げるためにプロセスを複数のスレッドに分割し、分割したスレッド同士を並行して動くようにした状態のことです

バッチ処理
あらかじめ登録した一連の処理を自動的に実行する仕組みで、日単位や月単位でプログラムを実行したい場合などに利用します。

MDM
「Mobile Device Management」の略で、社員が仕事で使用するスマートフォンなどの携帯情報端末の設定などを管理することをいいます。

NTP
ネットワークに接続される機器において、機器が持つ時計を正しい時刻へ同期するための通信プロトコルをNTP（Network Time Protocol）といいます。
電子メールなどで、違う機器でも同じ時間を表示できるように、ネットワーク上で時間を同期してくれます。

BYOD(Bring your own device)
個人の携帯機器を職場へ持ち込み、業務で使用することを指します。

POSは販売時点情報管理（Point of sale system）
商品がいつ何個売れたかや購入者の属性を、その商品単位で集計して管理することです。
SoXを使ったPodcastファイルの最適化

# はじめに

[xR.fm](https://xrfm.github.io/)というPodcastをやっているのですが、このご時世でリモートでの収録がメインになりました。そうなると気になるのが会話のラグで、しばし無音区間が生じてしまう状況になりました。そこで、SoX（Sound eXchange, the Swiss Army knife of audio manipulation）というライブラリを使って最適化を行いました。

# コマンド

```bash
# ノイズ除去
$ sox source.wav -n noiseprof noise.prof
$ sox source.wav noise_removed.wav noisered noise.prof 0.2

# コンプレッサ
$ sox noise_removed.wav compressed.wav compand 0.01,1 -90,-90,-70,-70,-60,-20,0,0 -5

# 無音部分の削除
$ sox compressed.wav silence_removed.wav silence -l 1 0.1 1% -1 0.8 15%
```

パラメータ等は調節してご利用ください。

## 結果

冒頭6秒当たり、「パーソナリティのなかじです」に続く「ikkouです」までに、実際はレス待ちの無言時間があったのですが、変換後はその場にいるような速さで聞こえるようになりました。

[第61回「門外不出モラトリアム」 | xR.fm](https://xrfm.github.io/episode/61)

# 参考にした記事

## ノイズ除去

[soxコマンド - memo](https://sites.google.com/site/memo73737/os/linux/soxcommand)

## コンプレッサ

[文化ヒナゲシ制作所雑記帳](http://matosus304.blog106.fc2.com/blog-category-9.html)

[sox - compand - dynamic range compression - Doom9's Forum](https://forum.doom9.org/showthread.php?t=165807)

[音楽ファイル編集コマンド sox の compand オプションを調べてみた - Qiita](https://qiita.com/osamasao/items/ea69a952fc0acb62dfd6)

## 無音部分の削除

[The SoX of Silence](https://digitalcardboard.com/blog/2009/08/25/the-sox-of-silence/)

# 最後に

実際にはMacアプリにして使っています。
ほぼ手間をかけずに音声が劇的に聞きやすくなってとても便利だと思いました。
在席確認ツールirucaのAPIをVB.Netから叩いて在席状態を更新する

#投稿の経緯
VB.Net→API（GET）のサンプルはネット上にたくさんあるのに、
VB.Net→API（PUT）のサンプルはなかなか見つからない！
やっと見つけてもC#のサンプルで、そのままだとうまく動かなかったり・・・
APIを叩くのは初めてで苦労したので、最終的に動いたものを投稿します。

#VB.Net→iruca-API（PUT）
```vb:呼び出し側
　　Call メンバー情報を更新する（"11111","離席"）'11111は在席状態を更新したい人のMEMBER-ID
```
```vb:メンバー情報を更新する
    Public Sub メンバー情報を更新する（メンバーID As String, 在席状態 As String)

        'ルームコード設定
        Dim ルームコード As String = "aa1111a1-1111-11aa-1a1a-a1111a111a11" 'irucaのROOM-CODEを入力

        '定義
        Dim ターゲットURL As String = "https://iruca.co/api/rooms/" & ルームコード & _ 
                                     "/members/" & メンバーID
        Dim PUTする文字列 As String = "{""status"":""" & 在席状態 & """}"　
　　　　　　　　　　　　　　　　　　　　'「"」で囲われた中の範囲は、2個重ねることで「"」を無理矢理使用OK
        Dim bytes As Byte() = Encoding.UTF8.GetBytes(PUTする文字列)
        Dim request As HttpWebRequest = CType(WebRequest.Create(ターゲットURL), HttpWebRequest)

        '通信の種類を設定
        request.Method = "PUT"
        request.ContentType = "application/json"　'irucaのapiとのやりとりはjson
        request.Accept = "application/json"

        '書き込み
        Dim stream As Stream = request.GetRequestStream
        stream.Write(bytes, 0, bytes.Length)
        stream.Close()

        '応答
        Dim response As HttpWebResponse = CType(request.GetResponse, HttpWebResponse)
                                                                   'ここで書込みが完了
        Dim reader As StreamReader = New StreamReader(response.GetResponseStream)
        response.Close()
        reader.Close()
    End Sub
```
#PUTが通る条件をFiddler（フリーソフト）で試行錯誤

文字コードやBodyの文字列の条件をFiddlerで確認
条件を入れてからExcuteボタンを押して、結果のところに赤が出なければOK！
サーバに送る前にエンコードが必要なの？といった疑念を解消できてスッキリできます。

![fiddler.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648912/bc0edfa4-f5ff-2f2e-da14-a0457d8a0cf4.gif)

#メンバー情報更新API
|HTTPメソッド|パラメータ|https://iruca.co/api/rooms/ROOM-CODE/members/MEMBER-ID　|
|-----------|------------------|--------------------------------------------------|
|PUT        |name	       |名前（省略可能。省略時は更新されません）　　　　   |
|       |status	       |ステータス（必須。在席、離席など）        　　　　|
|        |message           |ひとこと（省略可能。省略時は更新されません）　|

#リンク
[ログイン不要の在席管理ツール：iruca](https://iruca.co/)
[iruca API ドキュメント](https://iruca.co/api)
Flutter で iOS の touchDown 、Android の onTouch を実装する方法



## 想定する読者の方
・iOS でいうと touchDown 、Android でいうと onTouch を、Flutter でどう実現するか分からない方
・GestureDetector class を触ったことがない方
・GestureDetector class は分かるんだけど、書き方を忘れてしまった方

## 実装方法

GestureDetector class を利用すれば、各種タップやドラッグなどを実装できます。
https://api.flutter.dev/flutter/widgets/GestureDetector-class.html

色々な Callback(イベント)がありますが、今回は onTapDown を利用します。

## サンプルコード抜粋
``` dart
GestureDetector(
        // Widget をタップした瞬間にイベントが発火する
        onTapDown: (TapDownDetails details){
          //画面の座標を取得する(全画面の左上が0,0)
          print(details.globalPosition.toString());
          //child の座標を取得する(child の左上が0,0)
          print(details.localPosition.toString());
        },
      child: Container(width: 100, height: 100, color: Colors.blue),
    );
```

## サンプルコードのプロジェクト(Github)
https://github.com/grayplain/flutter_touch_down_sample
Git 現在のブランチを名前指定せずにpushする

## 提起

```shell-session
$ git push
fatal: The current branch feature/issue-xxx has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin feature/issue-xxx
```

リモートリポジトリと関連付いてないローカルブランチをプッシュしようとするとこのメッセージが表示されます。

```shell-session
$ git push --set-upstream origin feature/issue-xxx
```

メッセージで言われる通りのコマンドを実行すればプッシュされますが、typoも怖いし毎度ブランチ名を指定するのは億劫ですね。

## 解決

```shell-session
$ git push -u origin HEAD
```

現在のブランチをリモートリポジトリに同じ名前でプッシュする便利な方法です。

- `-u` は `--set-upstream` の省略オプション
  - 2回目以降は `git push` でok

## さらに楽する

`push.default` に `current` の値を設定します。

```shell-session
$ git config --global push.default current
```

http://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault

```shell-session
$ git push
```

現在のブランチ名と同じ名前でリモートリポジトリへpushしてくれます。

## 参考

- https://git-scm.com/docs/git-push#Documentation/git-push.txt-codegitpushoriginHEADcode

## 他に書いたGit関連の記事

- [Git関連の記事一覧](https://qiita.com/search?q=user%3Aucan-lab+tag%3AGit&sort=created)
MySQL エラーコードの意味を出力する

# 目的

- MySQLにて数字にて出力されるエラーコードの意味を出力するコマンドを紹介する

# 実行例

- 下記にエラーコードの意味を出力するコマンドを記載する。

    ```terminal
    $ perror エラーコードの数字
    ```

# 具体例

- エラー`ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)`のエラーコードの意味を出力する場合は下記コマンドを実行する。

    ```terminal
    $ perror 111
    >OS error code 111:  Connection refused
    ```
HCIて何なの

##HCIって何なの？
HCIについて調べた内容を備忘録としてアップします。

##HCIとは
ハイパーコンヴァージド・インフラストラクチャの略称です。

Wikipediaによると、
> ハイパーコンヴァージド・インフラストラクチャ（HCI、英: Hyper-Converged Infrastructure）は、コンピュータシステムにおける計算機能、ネットワーク機能、ストレージ機能といった基盤機能を、仮想化機能と標準的なハードウェアだけを用いて実装し、水平スケールを容易にしたシステムアーキテクチャ、あるいはこのアーキテクチャを採用したアプライアンス製品群の名称。

うん、わからん。
ということで、以下の動画を見ました。

https://m.youtube.com/watch?v=nquP4J2YNOE

##要約
ソフトウェア処理で、サーバ、SAN、ストレージ全てを単一HWに統合。

・運用が楽
ハイパーバイザー管理して、vm管理して、SANも管理して、ストレージは別で管理という地獄からの解放。

・コンパクト(2u)

・拡張性が高い
追加するのも、lanに繋いで自動検出で追加できる

・データの保存
raid構成ではなく各サーバのローカル上にデータを保管。
基本はローカル保存を大切にしている。
あわせて、分散保存もする。(ローカルにある方が処理速い)

1つ壊れても、データは他に分散されているので安心。
WSLのawkのバージョンを調べてみた(Windows10を無料で入手後):Awk 4.1.4

pretty-printがありました。

(参考)Windows7ライセンスの付与されたPCに対してアップグレードをかけるという手法になります。＜2020年でもWindows10を無料で入手する方法
https://mazu-bunkai.com/bunkai-wp/windows/9521/
上のパソコンに、WSLをインストールして、awkをみてみた。
（以下一部抜粋）
###Ubuntu 18.04.2
```
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
```
###GNU Awk 4.1.4
```
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)
Copyright (C) 1989, 1991-2016 Free Software Foundation.
```
###GNU Awk 4.1.4 help
```
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:                GNU long options: (standard)
        -f progfile                --file=progfile
        -F fs                        --field-separator=fs
        -v var=val                --assign=var=val
Short options:                GNU long options: (extensions)
        -b                        --characters-as-bytes
        -c                        --traditional
        -C                        --copyright
        -d[file]                --dump-variables[=file]
        -D[file]                --debug[=file]
        -e 'program-text'        --source='program-text'
        -E file                        --exec=file
        -g                        --gen-pot
        -h                        --help
        -i includefile                --include=includefile
        -l library                --load=library
        -L[fatal|invalid]        --lint[=fatal|invalid]
        -M                        --bignum
        -N                        --use-lc-numeric
        -n                        --non-decimal-data
        -o[file]                --pretty-print[=file]
        -O                        --optimize
        -p[file]                --profile[=file]
        -P                        --posix
        -r                        --re-interval
        -S                        --sandbox
        -t                        --lint-old
        -V                        --version

To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.

gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.

Examples:
        gawk '{ sum += $1 }; END { print sum }' file
        gawk -F: '{ print $1 }' /etc/passwd
```
AWS: セキュリティとアイデンティティ

# セキュリティとアイデンティティ
## セキュリティとアイデンティティ
### AWSのアカウントの種類
AWSにはAWSアカウントとIAMユーザーと呼ばれる2種類のアカウントがある。

- AWSアカウント
    - AWSのすべてのサービスをネットワーク上のどこからでも利用可能
    - ルートユーザーとも言われる
- IAMアカウント
    - AWSを利用する各利用者向けに作成されるアカウント
    - 必要に応じて*AWSアカウント*ユーザーにより作成される
    - AWSの各利用者がWebコンソールログインして操作するとき、APIを利用してAWSを操作するときなどに利用
    - IAMユーザーには最小限の権限を付与することでセキュリティの安全性を高めることができる

### IAMの機能
1. AWSサービスやAWSリソースに対する操作権限をIAMポリシーとして定義
2. IAMポリシーをIAMユーザーやIAMグループにアタッチする
3. IAMユーザー、IAMグループに属するIAMユーザーがマネジメントコンソールにログインすると、付与された権限の操作を行うことができる

### IAMポリシー
Acion(サービス), Resource(機能や範囲), Effect(許可/拒否)という3つの大きなルールに基づいて、AWSの各サービスを利用する上での様々な権限を設定

- インラインポリシー
    - 対象ごとに個別に適用する
- 管理ポリシー
    - 複数のユーザー・グループにまとめて適用する
- AWS管理ポリシー
    - AWSによって用意されたもの
- カスタマー管理ポリシー
    - ユーザー自身が管理するもの

### IAMユーザーとIAMグループ
ユーザーとは、AWSを利用するために各利用者に1つずつ与えられている認証情報のこと。

- ユーザーIDとパスワード
    - Webコンソールにログインする際に利用
    - Multi-Factor Authenticationを推奨
- アクセスキーとシークレットアクセスキー
    - CLIやAPIからAWSのリソースにアクセスする場合に使用

### IAMロール
IAMロールは、一時的にAWSリソースへのアクセス権限を付与するときに利用

- AWSリソースへの権限付与
    - EC2インスタンス上で稼働するアプリケーションに一時的にAWSのリソースへアクセスする権限を与えたい
- クロスアカウントアクセス
    - 複数のAWSアカウント間のリソースを1つのIAMユーザーで操作したい
- IDフェデレーション
    - 社内のAD(Active Directory)サーバーに登録されているアカウントを使用して、AWSリソースにアクセスしたい
- Web IDフェデレーション
    - FacebookやGoogleのアカウントを使用してAWSリソースにアクセスしたい

## KMSとCloudHSM
KMS(=AWS Key Management Service)は、AWSが管理するマネージドサービスで、多くの場合、CloudHSMではなくこちらを用いる

CloudHSM(=AWS CloudHSM)は、VPC内で専有のハードウェアを利用して鍵を管理するサービスで、相当に大規模なシステムに用いる

### KMSとCloudHSM

||CloudHSM|KMS|
|---|---|---|
|専有性|VPC内の専有ハードウェアデバイス|AWSが管理するマルチテナント|
|可用性|ユーザー側が管理|AWS側が高可用性・耐久性を設計|
|信頼の基点|ユーザー側が管理|AWS側が管理|
|暗号化機能|共通鍵及び公開鍵|共通鍵|
|コスト|ほぼ固定|従量課金|

### KMSの機能
KMSでは、データキーでデータを暗号化し、データキーをマスターキーで暗号化する。（エンベロープ暗号化）

- Encrypt: 暗号化API
- Decrypt: 復号化のAPI
- GenerateDatakey: ユーザーがデータの暗号化に利用するためのカスタマーデータキーを作成する

### マスターキーとデータキー
- Customer Master Key
    - データキーを暗号化するための鍵
- Customer Data Key
    - データを暗号化するための鍵

## AWS Certificate Manager
### 証明書の役割と種類
1. 経路間通信の安全性の確保
2. 通信している相手が誰かの証明

- 自己証明書: 自分で認証局をたてて証明書を発行(第三者による保証無し)
- ドメイン証明(DV): ドメインの所有のみを証明。組織情報の確認はされない
- 組織認証(OV): 組織情報の審査を経てから認証する
- 拡張認証(EV): OVより厳格な審査で認証する。アドレスバーに組織名が表示される
- 
### ACM
AWS Certificate Manager(ACM)は、AWS自身が認証局になってDV証明書を発行するサービス。
ACMは、AWS自身が認証局となって、RSA鍵とサーバー証明書の作成・管理を行うサービス。
【AWS SAP】AWS WAF【頻出】

##AWS SAP取得に向けて勉強する中で覚えてよかったもの 第16弾
以下の違いについて覚えておいて損はありません。

・AWS WAF

##AWS WAFとは
そもそも、WAFはWeb Application Firewallの略称です。

アプリケーションを保護してくれます。
AWS WAFは、一般的なウェブの脆弱性からアプリケーションを保護します。

(以下、公式サイトより)
> AWS WAF は、可用性、セキュリティ侵害、リソースの過剰消費といった一般的なウェブの脆弱性からウェブアプリケーションまたは API を保護するウェブアプリケーションファイアウォールです。AWS WAF では、SQL インジェクションやクロスサイトスクリプティングなどの一般的な攻撃パターンをブロックするセキュリティルールと、定義した特定のトラフィックパターンを除外するルールを作成できるため、トラフィックがアプリケーションに到達する方法を制御できます。AWS または AWS Marketplace 販売者が管理する事前設定済みのルールセットである AWS WAF のマネージドルールを使用して、すぐに開始できます。WAF のマネージドルールは、OWASP トップ 10 のセキュリティリスクなどの問題に対処します。これらのルールは、新しい問題が発生すると定期的に更新します。AWS WAF には、セキュリティルールの作成、デプロイメント、およびメンテナンスを自動化するために使用できる、完全な機能を備えた API も含まれています。
raspberry piで温度センサ(DS18B20)の値を取得する

## 本書の目的

DS18B20の設定方法はGoogle検索でいくらでも情報が見つかるのだが、少し戸惑ったので、2020年6月時点における動作確認結果のメモとして投稿する。

## 構成

ハード構成

* Raspberry Pi Zero WH
* センサ DS18B20
  AliExpressで購入。(https://www.aliexpress.com/item/32676135779.html)

ソフト構成：

```
sudo lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:        10
Codename:       buster

uname -a
Linux dishproto01 4.19.97+ #1294 Thu Jan 30 13:10:54 GMT 2020 armv6l GNU/Linux
```

## 接続方法

4.7KΩの抵抗をVCCとDQの間に接続（プルアップ）する。(ここに10KΩの抵抗を使用したらデバイスがLinux上で見つからず戸惑った）

JP1の各ピン番号がRaspberry Piのピン番号に対応している。
1=3.3V
7=GPIO4(Raspberry Piにおける、1-Wire用のデフォルトピン）
39=GND

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189186/498d206b-3dd1-3b53-7f46-bbb48d0cf0db.png)

## 設定方法

/boot/config.txtの末尾に以下の行を追加する。
(`raspi-config`を使ってもよいが、やることは同じ)

```/boot/config.txt
dtoverlay=w1-gpio
```

再起動する

```bash 
sudo reboot
```

再起動後、以下のように、28-で始まるディレクトリが出現する。

```bash
ls /sys/bus/w1/devices/
28-3c01a81689e9  w1_bus_master1
```

ちなみに28-の部分は、デバイスの種類によって変わる模様。
https://github.com/owfs/owfs-doc/wiki/1Wire-Device-List

28-～のディレクトリ内のw1_slaveファイルの内容を表示すると、t=・・・で温度が表示される。(watchコマンドにより、0.5秒ごとに更新）

```bash
ash
watch -n 0.5 cat /sys/bus/w1/devices/28-3c01a81689e9/w1_slave
```

```:表示内容
Every 0.5s: cat /sys/bus/w1/devices/28-3c01a81689e9/w1_slave                    

c8 01 55 05 7f a5 a5 66 83 : crc=83 YES
c8 01 55 05 7f a5 a5 66 83 t=28500
```
コンテナ内の仮想インタフェースがホスト側のどの仮想インタフェースに対応するかを調べる

Dockerの場合はホスト側でこのワンライナー叩けばいけます。

```
ip link | grep -E "^`sudo docker exec container_name cat /sys/class/net/eth0/iflink`:"
```

コンテナの外でパケットをキャプチャしたい場合など、ホスト側のインタフェース名はランダムで生成されるため、対応関係がわかりにくいです。
それを調べる方法が上記のコマンドです。

ホスト側の仮想インタフェースのうち、ifindex値がコンテナ内の仮想インタフェースのiflink値と同じものが対応するインタフェースになります。
LXCでも仕組みは同じだと思うので、iflink値を元にして探せると思います。（未検証）
【AWS SAP】AWS shield【頻出】

##AWS SAP取得に向けて勉強する中で覚えてよかったもの 第14弾
以下サービスについて覚えておいて損はありません。

・AWS shield

##AWS shieldとは
DDoS対策のためのサービス。
AWS Shield StandardとAWS Shield Advancedが存在します。

＊AWS Shield Standard
追加費用なし。
YN/ACK フラッド、リフレクション攻撃、HTTPスローリードなど、今日最も一般的な攻撃の96％から守ってくれます。

＊AWS Shield Advanced

ボリューム攻撃に対する追加のDDoS軽減機能、インテリジェントな攻撃検出、アプリケーションおよびネットワーク層での攻撃に対する軽減を提供。

DDoS攻撃の影響で請求金額が急増することを防ぐために、AWSのDDoSレスポンスチーム(DRT)が24時間365日サポートしてくれます。

利用料金は高め。

(以下、公式サイトより)
> AWS Shield はマネージド型の分散サービス妨害 (DDoS) に対する保護サービスで、AWS で実行しているアプリケーションを保護します。AWS Shield ではアプリケーションのダウンタイムとレイテンシーを最小限に抑える常時稼働の検出と自動インライン緩和策を提供しているため、DDoS 保護のメリットを受けるために AWS サポートに依頼する必要はありません。AWS Shield にはスタンダードとアドバンストの 2 つの階層があります。

参考)

AWS Shield – DDoS攻撃からアプリケーションを保護
https://aws.amazon.com/jp/blogs/news/aws-shield-protect-your-applications-from-ddos-attacks/