OmniAICreator/Qiita-1.07M huggingface dataset:
【React】カスタムフックで大量のuseCallbackを楽に記述する

Material UIを使ってフォームを作成するとき、テキストフィールドなどはコンポーネント化しちゃいますよね。

親コンポーネント（入力フォームのページ）ではuseStateで入力値を管理する。

その時に、子コンポーネント（テキストフィールド）にonChange用の関数を渡すので、useCallbackでsetState関数をメモ化して上げる必要があります。

```tsx:src/components/TextInput.tsx
import React from 'react'
import TextField from '@material-ui/core/TextField'

interface TextInputProps {
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void
  value: string
}

const TextInput = (props: TextInputProps) => {
  return (
    <TextField
      value={props.value}
      type={"text"}
      onChange={props.onChange}
    />
  )
}

export default TextInput
```

```tsx:src/index.tsx
import React, {FC, useEffect, useState} from 'react';
import TextInput from 'src/components/TextInput'

const Hoge: FC () => {
  const [name, setName] = useState<string>('');
  const inputName = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    setName(event.target.value)
  },[setName])

  return (
    <form>
      <TextInput onChange={inputName} value={name} />
    </form>
  )
}
```

このようなテキストフィールドが1つならいいけど、複数あると、毎回useCallbackを作るのがバリ面倒です。

なので、useCallbackでメモ化された関数を作るカスタムフックを作成しました。

```ts:src/lib/customHooks.ts
import React, {useCallback, SetStateAction, Dispatch} from 'react'

export const useStringChangeEventCallback = (update: Dispatch<SetStateAction<string>>) => {
  return useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    update(event.target.value)
  },[update])
}
```

こうして使います。

```tsx:src/index.tsx
import React, {FC, useEffect, useState} from 'react';
import TextInput from 'src/components/TextInput'
import {createStringChangeEventCallback} from 'src/lib/customHooks'

const Hoge: FC () => {
  const [name, setName] = useState<string>(''),
    [address, setAddress] = useState<string>(''),
    [companyName, setCompanyName] = useState<string>('');

  return (
    <form>
      <TextInput
        onChange={useStringChangeEventCallback(setName)}
        value={name}
      />
      <TextInput
        onChange={useStringChangeEventCallback(setAddress)}
        value={address}
      />
      <TextInput
        onChange={useStringChangeEventCallback(setCompanyName)}
        value={companyName}
      />
    </form>
  )
}
```

これで入力フィールドがたくさん必要なフォームだとしても、スッキリ書けますね！！！

数値型の入力フィールドならこんな関数を用意しておくのもアリ。

```ts:src/lib/customHooks.ts
export const useNumberChangeEventCallback = (update: Dispatch<SetStateAction<number>>) => {
  return useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    if (/^[0-9]+$/.test(event.target.value)) {
      // event.target.valueは文字列型なので、数値型に変換する
      update(Number(event.target.value))
    }
  }, [update])
}
```

## 2020/09/19追記
Reactコンポーネント以外で `useCallback` などのHooksを使う場合、eslintに `react-hooks/rules-of-hooks` のルールを入れているとエラーになります。
縛りを緩めることになりますが、この方法を採用するなら、lintのルールから抜いてください。
## 2020/10/20追記
関数名を修正。
そもそもカスタムフックを作るときは use~~~ という関数名で作れば、上記lintで怒られることもありませんでした。
エラー文と[ドキュメント](https://ja.reactjs.org/docs/hooks-custom.html)はよく読もう。(自戒)
ScalaでString型を列挙型に変換する

# 概要
REST API等で定義した文字列の値を、
scalaで `case objcet` を使ってenum(っぽいやつ)を定義した値に `string型` から変換したいことがあると思います。

今回、いい感じに `string型` から定義したenum(っぽいやつ)に変換する処理を実装したので記事にしておこうと思います。

# そもそもscalaにenumはないけども
scalaにはそもそもenumがないので、[この記事](https://qiita.com/inabe49/items/c4db33aa03228a6a78f4)のようなやり方を使って実現してます。


## 作ったコード

```scala
abstract sealed class OrderParameter {
  def getOrderQuery(hb: HogeObject) = {
    this match {
      case MODIFIED_AT => hb.modifiedAt.desc
      case SORT_NUMBER => hb.sortNumber.asc
      case PUBLISH_AT  => hb.publishedAt.desc
    }
  }
}
object OrderParameter {
  def fromString(value: String): Option[OrderParameter] = {
    Vector(MODIFIED_AT, SORT_NUMBER, PUBLISH_AT).find(_.toString == value)
  }
}
case object MODIFIED_AT extends OrderParameter
case object SORT_NUMBER extends OrderParameter
case object PUBLISH_AT extends OrderParameter
```

実際に作ったクラスはこちらになります、このクラスを呼び出し元で次のように使ってあげることでいい感じにstringから変換できます。

## 呼び出し元

```scala
def func(order: String): Action[AnyContent] = Action.async {
OrderParameter.fromString(order) match {
      case None => Future {
        BadRequest(Json.toJson(ErrorResponse(
          400, "パラメータが不正です"
        )))
      }
      case Some(orderParameter) => {
        for {
          content <- hogeObjectDao.findAll(orderParameter) # hb.modifiedAt.desc を使ってsortByをかけれる処理を作る
        } yield {
          content match {
            case Some(res) => {
              Ok(Json.obj("results" -> res))
            }
            case None => NotFound(Json.toJson(ErrorResponse(
              404, "Not Found"
            )))
          }
        }
      }
    }
```
apiで呼び出された時とかに `order` というパラメータを `OrderParameter` のobjectと同じ名前でStringで指定してあげれば、変換できない場合はエラー、変換できた場合は`OrderParameter`としてプログラム内で使えるようになります。


# まとめ
せっかく型がしっかりしている言語を使っているので、RESTAPIとかで受け付けるパラメータも型っぽく振る舞えるようにしたいですよね。
こうすることで、指定できるパラメータを制限できるので安全な実装になるかと思います。
【しくじり設計】NAS & クラウドバックアップ　Amazon S3 vs box

# 【しくじり設計】NAS & クラウドバックアップ　Amazon S3 vs box
最近台風、豪雨、猛暑にコロナと地球がやばいですね。
災害の話題が多くなるにつれて、中小企業様向けにBCP/DR対策のソリューションを提案することが非常に多くなってきました。
この度ローカルに設置してあるNASのデータのバックアップ先として、Amazon S3もしくはboxを使うパターンで、「しくじり設計」をしてしまったので懺悔および備忘録として記事にします。

バックアップ先としてのAmazon S3 とbox について、どういう使い分けをすればよいか皆さんの参考になれば幸いです。

# ソリューション設計概要
・ローカルにNASを設置して、ファイルサーバとして利用する　※QNAP製NASを使ってます
・NASのバックアップアプリ(HBS3)を利用し、NAS内の指定フォルダのデータをクラウドストレージにコピーする
・NASから前回バックアップ時からのデータ差分を定期的にバックアップする　※初回はフルバックアップ
・クラウドストレージはAmazon S3(標準ストレージ = 0.025USD/GB) もしくはbox(Business Plan = 1ID/1,800円)を利用する

# Amazon S3 とbox について
詳しくは公式Webサイト参照してください。
[Amazon S3](https://aws.amazon.com/jp/s3/?nc=sn&loc=0)
[box](https://www.box.com/ja-jp/home)
どちらとも無制限に容量拡張可能なストレージサービスですが重要なポイントは以下です。

①料金体系のちがい
　・Amazon S3 は使用するストレージ容量による「従量課金」
　・boxは利用するユーザ数（ライセンス数）による「ID数課金」

②APIのアクセスレート制限のちがい
　・Amazon S3は1バケットへのアップロードリクエストで3,500 リクエスト/秒
　　　[公式情報](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/optimizing-performance.html)
　・boxは1ユーザーあたりのファイルアップロードリクエストは40件/秒
　　　[公式情報](https://ja.developer.box.com/guides/api-calls/permissions-and-errors/rate-limits/)

# ケース
3拠点に設置してあるNASから合計12TB(4TB×3台)のデータのバックアップをする

* **しくじりポイント**

・APIアクセスレート制限を考慮せず、コストを安く出来るということだけで、boxを選択したこと

 合計容量12TBのデータのバックアップ先としてAmazon S3とboxを比較検討したときに
【バックアップ目的で使い、一般ユーザはアクセスしないので管理者5人分のライセンスだけの購入でOK】、【ストレージはそこそこ大容量が必要】という条件のため、必要最低限の5ライセンス購入すれば、定額でストレージ容量無制限に利用できるboxを選択しました。

　（費用のサンプル）
　box →　1,800円 × 5ID = 9,000円/月
　Amazon S3 →　＄0.025 × (1024GB×12) = ＄307.2/月 
　　　　　　　　　　　　　　※$1=110円換算で約33,800円

たしかに同じ12TBのデータバックアップですがboxを使った方がかなり安くはなります。

* **発生した問題**

・バックアップ処理が全然終わらない...
　初回のフルバックは3日～5日かかり、差分バックアップでも1拠点あたり3時間ほどかかる...

原因は単純に*<font color="Red">APIへのリクエストレート制限</font>*です。
3拠点それぞれからbox APIへアップロードリクエストを送るのですが、リクエストできるレート制限に引っかかって全然データのバックアップ処理が進まないという事態に陥りました...
ちなみにQNAP NASではこんな感じでエラーログが表示されます。

    [Hybrid Backup Sync] Backup job "バックアップジョブ名": Cloud storage service is unavailable or has exceeded its request threshold. Attempting to retry.
しかもこのエラーが１分おきぐらいに発生するので、ログが凄いことになります...

1拠点で1台のNASからのアクセスであれば、リクエスト数がレート制限を大幅に超えることはなかったかもしれませんが、3台から一気にリクエストがいってしまったので、制限かけられたということみたいです。



<br>

* **反省点**<br>
どのくらいAPIリクエストが発生するのかは、きちんと考慮しましょう！
バックアップであれば、データ容量だけでなく、データのオブジェクト数も考えましょう！
もしわからなければ無難にAmazon S3を選択することをおすすめします。

# 最後に
クラウドストレージを正しく使えば、コスパの良いBCP/DR対策が出来ます！
今回は私のようなへっぽこSEが残念な設計でboxを使ったことで、トラブルが勃発しましたが、box自体はかなり便利なサービスです。正しく仕様を理解し、BCP/DR対策を進めましょうd(‘・ω・’)
スプレッドシートで微分擬き

## はじめに

慣れ親しんだ表計算ソフトだけで微分がしたい。これから紹介するのは、そんな思いを抱える一人のノンプログラマが、小一時間で編み出した泥臭い力技である。導関数を求めることは無理でも、微分係数に当たりを付けることは可能だと気が付いたのだ。解説に入る前に、計算の流れを説明する。

## 計算の流れ

関数f(x)について、
1. 変数xを適当な値aと置く。
2. 普通にf(a)を計算する。
3. daをaに比例した微小な値a*10^-10などと置く。
4. f(a+da)を計算する。
5. 項目2,3,4を使って、(f(a+da)-f(a))/daを計算する。

以上。何をやっているかというと、微分の定義そのものから、極限の計算を省いた、言わば微分擬き。単純だが、いざ表計算ソフトでやろうとすると躓きうるので、以下に詳細を解説する。

## 詳細

今回は、適当にx=0,±1,±2,±3,±4,±5とする。

```:A2
=ARRAYFORMULA(ROW(A1:A11)-6)
```

![gs_derivative_001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694094/a6a279a0-5f86-f72b-4540-c8a564d78adb.png)

[`ARRAYFORMULA()`](https://support.google.com/docs/answer/3093275?hl=ja)は、Googleスプレッドシート独自の関数なので、Excel派の人は、引数を単一のセルにしてオートフィル。[`ROW()`](https://support.google.com/docs/answer/3093316?hl=ja)についても、リンクを参照。

次に、f(x)だが、今回は簡単のためx^2とする。

```:B2
=ARRAYFORMULA(A2:A12^2)
```

![gs_derivative_002.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694094/85991351-d2e7-ef03-baa0-1968a653bf98.png)

次のdxは、限りなく0に近い値にしたいが、それはあくまで「xと比較したときに」という前提のもとである。今回は、適当にdx=x*10^-10とした。微分係数の必要な桁数に応じて、調整いただきたい。

```:C2
=ARRAYFORMULA(A2:A12*10^-10)
```

![gs_derivative_003.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694094/a7697dda-a7fb-9d08-8682-7ffdd83ecf49.png)

さて、次のf(x+dx)は、入力方法にポイントがある。今回は、x^2というシンプルな関数だから、問題ないかもしれない。しかし、これが複雑な多項式になったとき、数式の入力がかなり面倒になる。プログラミングの原則に、DRY(Don't repeat yourself)なるものがあるらしいが、これはスプレッドシートにおいても同じことだと思う。

具体的な話に戻ろう。D2セルには、f(x+dx)に当たる数式をそのまま打ち込むのではなく、B2セルから数式をコピペして、変数だけを置換してほしい。手順の例を書くと以下のようになる。

- B2セルを編集可能にする。
- 数式を全選択してコピー。エンターキーで編集を解除。
- D2セルを編集可能にする。
- 数式の貼り付け。エンターキーで編集を解除。
- D2セルを選択。
- 「編集」から「検索と置換」を選択。

![gs_derivative_004.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694094/b31af40e-da2f-fea4-f9d0-f21ac2a1877b.png)

- 下記のように入力。
  - 検索：`A2:A12`
  - 置換後の文字列：`(A2:A12+C2:C12)`
  - 検索：「特定の範囲」
  - 「数式内も検索」に☑

![gs_derivative_005.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694094/50817e11-ed8a-8175-e54d-b422bab52619.png)

- 「すべて置換」し、「完了」

なんということだろう。D2セルの数式が完成しているではないか。

```:D2
=ARRAYFORMULA((A2:A12+C2:C12)^2)
```

![gs_derivative_006.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694094/cc26deb8-e003-c631-4cc3-82aa6b65c14a.png)

最後に、(f(x+dx)-f(x))/dxを計算する。

```:E2
=ARRAYFORMULA((D2:D12-B2:B12)/C2:C12)
```

![gs_derivative_007.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694094/f2a3a15e-c2ce-2d2e-1063-ea6dcedff6fb.png)

これで、微分係数の当たりが付いた。

以上が、微分擬きの全容である。


## おわりに

賢明な読者ならお気づきだと思うが、x=0で所謂"zero division error"が吐かれている。割と致命的な課題である。[`IF()`](https://support.google.com/docs/answer/3093364?hl=ja)の類いを使用して、回避する方法もあると思うが、今回は力尽きた。

また、D2セルにおいて、[`SUBSTITUTE()`](https://support.google.com/docs/answer/3094215?hl=ja)を使わなかったのは、返り値がテキストになってしまうためである。本当は関数だけで済ませたかった。

今後は、上記手法の応用例などの記事も書きたい。

それでは、また。
has_manyで、scopeを使って絞り込む

merge で scope を指定すればOK。

```ruby:user.rb
has_many :team_members
has_many(
  :pro_team_member,
  -> { merge(Team.pro) },
  through: :team_members,
  source: :team,
)
```

「何をもってproとするか」は、 `Team` 側が持つべき知識なので、 `User` 側で無闇に `where(pro: true)` みたいなコードを書くのは避けた方がよいです。

ドメイン知識が他のオブジェクトに流出している感じがするので。
Zustand: React向け軽量ステート管理ライブラリ

## はじめに

本記事ではZustandという軽量ステート管理ライブラリを紹介します。ZustandはFlux/Reduxの流れを汲むステート管理ライブラリです。React向けに必要な機能だけに削ぎ落とし、シンプルなAPIを提供していることが特徴です。また、Contextを用いていないことも特徴の一つです。今回は技術的な側面よりも、基本的な使い方を紹介します。

##  インストール

```bash
npm install zustand
```

Zustandは「チュースタンド」のように読み、ドイツ語で「状態」を意味します。
追記2022/7/29: 私は最近はドイツ語読みはやめて、英語読みの「ザスタンド」か「ズゥスタンド」にしています。

## 一番簡単な例：「カウンター」

```tsx
import React from 'react';
import create from 'zustand';

// ステートの型を定義する、アクションもステートの一部
interface State {
  count: number;
  increment: () => void;
}

// ステートの実装からhookを作る
const useStore = create<State>((set) => {
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
});

// コンポーネントでhookを使う
const App: React.FC = () => {
  const { count, increment } = useStore();
  return (
    <div>
      {count} <button onClick={increment}>+1</buttoon>
    </div>
  );
};
```

上記例では、`useStore`はAppコンポーネントでしか使っていませんが、実際は複数のコンポーネントで何度でも使うことができます。

## セレクターによる限定的な読み込み

React-ReduxのuseSelectorに慣れている方にはすぐ伝わると思いますが、セレクターを指定することができます。

```tsx
const Action: React.FC = () => {
  const increment = useStore((state) => state.increment);
  return (
    <div>
      <button onClick={increment}>Increment count</buttoon>
    </div>
  );
};
```

この場合`increment`は通常変化しないため、この`Action`コンポーネントは`count`が変化してもre-renderしません。

storeに値を複数入れてそれを個別に読み込むこともできます。

```tsx
const useStore = create<State>((set) => {
  count1: 0,
  count2: 0,
  increment1: () => set((state) => ({ count1: state.count1 + 1 })),
  increment2: () => set((state) => ({ count2: state.count2 + 1 })),
});
```

## ちょっと複雑なアクション

アクションは複数の値を同時に変更することができます。アクションの作り方に制約はなく柔軟に作ることができます。

```tsx
const useStore = create<State>((set) => {
  count1: 0,
  count2: 0,
  multiplyCounts: (by) => set((state) => ({
    count1: state.count1 * by,
    count2: state.count2 * by,
  })),
});
```

非同期のアクションを作ることもできます。

```tsx
const useStore = create<State>((set) => {
  count: 0,
  fetchCount: async () => {
    const res = await fetch(...);
    const data = await res.json();
    set({ count: data.count });
  },
});
```

この例は、`set`に更新関数ではなく更新するオブジェクトを直接指定しています。

アクション内の処理でステートにアクセスしたい場合は第二引数の`get`を使うことができます。

```tsx
const useStore = create<State>((set, get) => {
  id: 'foo'
  count: 0,
  fetchCount: async () => {
    const res = await fetch('http://.../id=' + get().id);
    const data = await res.json();
    set({ count: data.count });
  },
});
```

## おわりに

以上が基本機能の紹介でした。基本と言っても、Reactで使う範囲では、この応用でおおよそのことが実現可能です。また、immerのとの組み合わせはとても強力ですし、Redux DevToolsにも対応しています。ぜひお試しください。

GitHub: <https://github.com/react-spring/zustand>
ExchangeOnline　メールフロー設定

１．ExchangeOnlineとは？
　マイクロソフトが開発したグループウェア/電子メールのサーバー製品であるMicrosoft Exchange Serverをマイクロソフト自身がホスティングをして提供しているクラウドコンピューティング型のサービスです。

２．メールフローの概要
　送受信される電子メールを検査し、免責事項の適用、メッセージのブロッ
ク、監査レビューのためのメールボックスへのBCC 送信などの様々なアクションを実行するために使用されます。

３．作業目的
　メールフローを使用することにより、特定条件のメールに上司承認を必要としたり、特手のメールを送受信拒否したりと様々なことが可能です。

４．作業手順
　例として、今回は特定のアドレスにメールが届いた際に、受信拒否する設定をご説明いたします。
　　①Microsoft365 管理センターを開く
   ![Ex1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/7237b795-55cf-10bb-df9a-5b5c0d8f92c3.png)

　　②左メニューバーの「すべてを表示」をクリックし、表示された管理センター内の「Exchange」をクリック
   ![Ex2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/88b87b28-2daf-a120-eae6-fc615a9772c4.png)

　　③Exchange管理センターが開くので、左メニューバーの「メールフロー」をクリック
   ![Ex3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/82cd2730-3a96-4f3f-3230-5e46bcd51794.png)

　　④「ルール」タブが選択されているのを確認し、「＋」新規作成をクリックして、「送信者または受信者でメッセージを制限する…」を選択
   ![Ex4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/0476d461-253f-0117-ac37-55a330c79b49.png)

　　⑤「このルールを適用する条件...」で「受信者のアドレスが次と一致する…」を選択
   ![Ex5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/1cdf043f-976c-da89-4410-09ea92b02668.png)

　　⑥「単語または語句の指定」のポップアップが表示されるので受信拒否したいアドレスを入力
   ![Ex6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/ad420dac-548c-01a4-b046-9e302ee99697.png)

　　⑦「実行する処理...」で「だれにも通知せずにメッセージを削除する」（送信側、受信側共に連絡なしで削除される）か「説明を示してメッセージを拒否する」→「拒否の理由の指定」を入力（送信者側には「拒否の理由の指定」で入力された文言をメールで送られる。受信側には連絡なしで削除される）を選択
   ![Ex7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/ece81b59-39de-6921-332d-8ab207321bbb.png)
   ![Ex8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/0552c93f-d1e2-dcdb-e6cd-8dc2f7077873.png)


　　⑧一番下の「保存」をクリック
   ![Ex9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/74034fea-f56a-1d0e-01c5-3ef2a1f03db9.png)


　以上の設定で指定したアドレスにはメールが届かないようになりました。
　
　※指定するアドレスはユーザーのメールアドレスだけではなく、グループメールアドレスでも設定が可能です。
GravioでChromecastに動画を流す: ラズパイ/Linux編

**(注) Gravio 4.6でChromecastコンポーネントが搭載され、CATTのインストールなくGravioからChromecastデバイスへのキャストが可能になりました。この記事はそれ以前のバージョンで試した古い記事です**

# 背景
[前回](https://qiita.com/zrock/items/522a629262222645aefe)、CATTを使ってChromecastデバイスに動画を流すところまでやりました。CATTの使い方はこちらをどうぞ。→ https://qiita.com/zrock/items/522a629262222645aefe
今度はこれをGravioで制御してみます。Gravioで制御できれば、いろいろ妄想が広がります。

* 人が来たらウェルカムメッセージを流す
* 温度によって、暑いときは涼しい映像、寒いときは温かい映像を流す
* ボタンを押して好きな映像を流す
* タイマーを使って目覚まし代わり

# 使用環境
前回と同じです。Gravioが増えてます。

* Raspberry Pi 4
* Ubuntu 20.04.01 LTS
* Python 3.8.2
* CATT v0.11.3
* Gravio HubKit v3.8.0-4681
* Gravio Studio v3.8.3606.0

# 概要
Gravioには**RunScript**というシェルスクリプトを実行するコンポーネントがあります。CATT自体には対応してませんが、シェルスクリプトを作ってこれを実行することで実現できます。

# 手順
まずはシェルスクリプトを作ります。動画をキャストするだけなのでデバイス名など埋め込んでしまいます。動画自体はパラメータで渡したいので `$1` を使っておきます。非常に単純です。

```shell:play-video.sh
catt -d "Chromecast 4K" cast "$1"
```

これを配置します。配置する場所は、Linuxの場合、`/var/opt/gravio/action/scripts`の下です。あとで出てきますが、Gravio Studioからもアップロード可能です。SSHなどで繋げる場合は、直接置いたりvimなどで作っちゃってもかまいません。

ファイルができたら、オーナーを**root**にし、実行権を与えておきます。こうしないと、**RunScript**コンポーネントで実行することはできません。

```shell
$ cd /var/opt/gravio/action/scripts
$ sudo chown root play-video.sh
$ sudo chmod +x play-video.sh
```

あとはGravioでの設定です。
Gravio Studioにログインし、アクションを作成します。
アクションの中に、**RunScript**コンポーネントを配置します。
![catt2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/80a4a751-9917-8833-13f1-36490b958bd6.png)
プロパティで、**ファイル**に先程作成したplay-video.shを指定します。すでに配置している場合は、ブラウズボタンをクリックして、play-video.shを選択してください。配置していない場合は、アップロードボタンを使ってローカル環境で作成したファイルを配置してください。ただ、配置しただけでは実行権が付きませんので、必ずSSHなどでアップロード先のフォルダにあるスクリプトファイルに上記のコマンドで実行権を与えてください。
**Arguments**には動画のURLを指定してください。

これで終わりです。あとは再生ボタンをポチッとクリックすると、指定したデバイスで動画が再生されます。

あとはこんな感じでボタンのクリックイベントのトリガーでアクションを割り当てたり、センサーの値によって実行されるトリガーを作ればIoTとChromecastのあわせ技が完成です。

![catt1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/c1871e03-8f49-46fa-e8b0-79305a52d031.png)

ちなみに、サイトを表示させるにはコマンドが`cast_site`となるので、別のシェルスクリプトを作っておきましょう。コマンドもパラメータで埋め込んでもいいのですが、スクリプトを変えた方がわかりやすいですね。

```shell:show-site.sh
catt -d "Chromecast 4K" cast_site "$1"
```


# 最後に
最初に書いたように、Gravioは色々なセンサーに対応していて、センサーの状態を見ながらいろいろなアクションを実行できるのでとても妄想が広がります。エンタープライズ版のAI Editionになると、顔認識も可能になるので、訪問した人によって好みの映像を流すなんてことも可能になりますね。
ちなみに、今回はLinux/Raspberry Piで実現しましたが、WindowsでもPythonをインストールすれば実現可能です。ちょっとしたコツがあるのでそれはまた後日。
Google OnAir Japanに参加しました

* 開催日程
   * 2020年7月15日（水）〜9月9日（水）(日本時間)

* 場所
   * オンデマンド配信
   * セッション、デモなどを、いつでも好きな時に見ることができる

* 主催
   * Google Cloud

* 申し込み
   * https://cloud.withgoogle.com/next/sf/japan (日本語)

* 費用
   * 無料



## セッション - 最適なコンピューティングの選択
* Google Cloudにいろいろなコンピューティングサービスがある
   * Firebase
   * Cloud Functions
   * App Engine
   * Cloud Run
   * Kubernetes Engine
   * Compute Engine

* 新規サービスやサービス環境移行は、どのサービスの選択が正しいか
   * この質問を答えると、まずは各サービスのメリッドを紹介する

### Cloud Functions
* クラウドサービスを構築して接続するためのサーバーレス環境
* イベント駆動、関数定義
* 経由：Cloud Pub/Sub, Cloud Storage, HTTPリクエスト

### App Engine
* 開発者はコード開発に集中
* サーバー管理が必要なし
* 素早いスケールアップとゼロまで縮小可能なスケールダウン
* 関心の事
    * コード
    * HTTPリクエスト
    * バージョン


### Cloud Run
* デプロイアプリケーション: HTTP の $PORT でリッスンするコードを持つコンテナイメージ
* 自由に設定可能な 1 から最大 80 の同時リクエスト数
* ゼロから数千のインスタンスの自動スケーリング


### Kubernetes Engine 
* Google によるマネージド Kubernetes
* クラスタの管理: コンピュートノード,ソフトウェアアップデート,クラスタオートスケーリング

### Compute Engine 
* 仮想マシンとネットワーク
* 事前構築されたイメージ、または独自のイメージを作成できる

### どのサービスの選択が正しいか
* 新規プロジェクト
    * Cloud Functions -> App Engine -> Cloud Run -> Kubernetes Engine -> Compute Engine
* サービス環境移行
    * Compute Engine -> Kubernetes Engine -> Cloud Run -> App Engine -> Cloud Functions
浮動小数点数コードのデバッグ Verificarlo のメモ

## 背景

C/C++ コードで浮動小数点数が正しいかとか, どのあたりに誤差が出やすいか調べたい.
(e.g. 桁落ちや情報落ちが起きるところとか)

## Verificarlo

https://github.com/verificarlo/verificarlo

https://www.vi-hps.org/cms/upload/material/tw29/Verificarlo.pdf

ちょうどその辺りうまくやってくれそうなツール.
モンテカルロ法で統計的に処理している感じっぽい.
内部的には C/C++ を LLVM IR に変換していろいろ処理しているっぽい.

## TODO

* [ ] 実際に使ってみる
Sinatra と Chartkick でグラフを描画する

# はじめに
前回作成した、*[家族用todoリスト](https://qiita.com/superrino130/items/20f588f6a8b4d607c081#)*を改良してグラフを描画してみました
#　完成画面
![20200828.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538241/7a0310f0-4acf-eaef-b2bb-4265c882e705.png)

# 設定
```main.rb
require 'sinatra'
require 'sinatra/reloader'
require 'date'
require 'active_record'
require 'rack/csrf'
require 'chartkick'　　# 追加
```
```bash.sh
$ ls public/
chartkick.js  main.js  style.css
```
publicに`chartkick.js`を仕込みます
# ソース
```main.rb
get '/' do
  con = ActiveRecord::Base.connection
  dat = con.execute("select users.name, scores.score, scores.point from users inner join scores on users.id = scores.user_id where scores.flag=0 order by users.name, scores.point")
  h = {name: '', data: {}}
  @graph_data = []
  tname = ''
  dat.each do |x|
    if x["name"] == tname
      h[:data][x["point"]] = x["score"]
    else
      tname = x["name"]
      if h[:name] != ''
        @graph_data << h.dup
      end
      h[:name] = x["name"]
      h[:data] = {}
      h[:data][x["point"]] = x["score"]
    end
  end
  @graph_data << h.dup
  erb :index
end
```
本来は、`ActiveRecord`をうまく使わないといけないのでしょうが、`SQL`直打ちでデータを取得します。

```index.erb
<%= line_chart @graph_data, min: 40, max: 100 %>
```
綺麗に描画されているのは、`gem`のおかげです。
# まとめ
+ Chartkick の作者さんありがとうございます
+ Sinatra でグラフを描画した

参照したサイト
*[Create beautiful JavaScript charts with one line of Ruby](https://chartkick.com/)*
*[RailsでChartkickを使ったグラフの実装(簡単だけど、かゆい所に手が届かない) -- Qiita](https://qiita.com/hukuro310/items/6be3ec8fe478e5c9a0ab)*
*[Railsでシンプルなグラフを扱うならchart-js-rails よりchartkickを使うべし -- Qiita](https://qiita.com/Y_uuu/items/0d57748954c7cdb9bbcb)*
[Python]randrange()とrandint()の違い

#環境
・Python 3.8.5
・osx10.15.6

#はじめに
`Python`で初めてランダムな数を用いるとき同じような表記があったので違いを記した。

#randrange()とは
`random.randrange(a, b)`は『a』から『b-1』までの整数を返す。
引数が1つの場合は『0』から引数マイナス1の整数を返す。

#random.randint()とは
`random.randint(a, b)`は『a』から『b』までの整数を返す。

#違いは
最後の数を含むか含まないかの違い！
`random.randrange(a, b)`の方は最後の値を含まないので`len(配列）`と組み合わせて
配列の繰り返し処理の便利です！

#参考
random関数について
・https://www.lifewithpython.com/2013/04/random.html
【ARKit】平面を検出し、大きさを更新する

##1.ARKitを使うための設定をする
####変数の設定

```Swift
let configuration = ARWorldTrackingConfiguration()//コンフィギュレーションの作成
@IBOutlet weak var sceneView: ARSCNView! //ARSCNViewの紐付け
```

####ViewDidLoad()

```Swift

 override func viewDidLoad() {
    super.viewDidLoad()
    self.sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints,ARSCNDebugOptions.showWorldOrigin]//座標と特徴点の表示
    self.configuration.planeDetection = .horizontal//水平面の検出
    self.sceneView.session.run(configuration)//セッション開始
    self.sceneView.delegate = self
        // Do any additional setup after loading the view.
    }
```

##2.SCNNodeを返り値に持つ関数の作成

```Swift
func createNode(planeAnchor: ARPlaneAnchor) -> SCNNode{
        let plameNode = SCNNode(geometry: SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z)))
        planeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.white
        planeNode.geometry?.firstMaterial?.isDoubleSided = true
        planeNode.position = SCNVector3(planeAnchor.center.x,planeAnchor.center.y,planeAnchor.center.z)
        planeNode.eulerAngles = SCNVector3(90.degreesToRadians,0,0)
        return lavaNode
    }
```

##3.renderer()に平面をが追加、更新された時の挙動を記述する。

####平面が追加された時
引数にdidAddがあるrendererを指定します。

```Swift
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
        let planeNode = createNode(planeAnchor: planeAnchor)
        self.sceneView.scene.rootNode.addChildNode(planeNode)
    }

```
####平面が更新された時
引数にdidUpdateがあるものを指定します。

```Swift
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
        node.enumerateChildNodes{ (childNode, _) in
            childNode.removeFromParentNode()
        }
        let planeNode = createNode(planeAnchor: planeAnchor)
        node.addChildNode(planeNode)
    }
```
Rustでトレイトを使ってVecを連想リストっぽく扱えるようにする

# はじめに
最近はOCamlのコードを読んでRustで実装しています。
OCamlのListモジュールには連想リストを操作する関数が用意されています。
私は連想リストというデータ構造を知りませんでした。 どうやら辞書やハッシュマップとは違うみたいです。
WikipediaによるとLisp, Scheme, OCaml, Haskellの標準ライブラリに連想リストが含まれているそうです。
（参考: [Association list - Wikipedia](https://en.wikipedia.org/wiki/Association_list)）

話は変わりますが、先日参加した[Shinjuku.rs #11](https://forcia.connpass.com/event/182303/)で
Vecに`lower_bound`を追加する方法を知りました。
トレイトを定義し、Vecに実装すればよいそうです。

この発表にインスパイアされ、Vecを連想リストっぽく扱えるようにトレイトを定義、実装してみました。

# コード

## トレイト
```rust
trait Assoc<'a, U> {
    fn assoc(&self, key: &str) -> Option<U>;
    fn remove_assoc(&mut self, key: &str) -> Option<(&'a str, U)>;
    fn mem_assoc(&self, key: &str) -> bool;
}
```

## 実装
```rust
impl<'a, U> Assoc<'a, U> for Vec<(&'a str, U)>
where
    U: Copy,
{
    /// keyに対応する最初のvalueを返す
    /// 見つからなかった場合はNoneを返す
    fn assoc(&self, key: &str) -> Option<U> {
        for elem in self {
            if elem.0 == key {
                return Some(elem.1);
            }
        }
        None
    }

    /// keyに対応する最初のペアを削除し、削除した要素を返す
    /// 見つからなかった場合はNoneを返す
    fn remove_assoc(&mut self, key: &str) -> Option<(&'a str, U)> {
        for (i, elem) in self.iter().enumerate() {
            if elem.0 == key {
                let a = self.remove(i);
                return Some(a);
            }
        }
        None
    }

    /// keyが連想リストに含まれていればtrueを返す
    /// keyが連想リストに含まれていなければfalseを返す
    fn mem_assoc(&self, key: &str) -> bool {
        for elem in self {
            if elem.0 == key {
                return true;
            }
        }
        false
    }
}
```

## 例
```rust
fn main() {
    let mut v = vec![("a", 1), ("b", 2), ("c", 3)];

    assert_eq!(v.assoc("a"), Some(1));
    assert_eq!(v.assoc("b"), Some(2));
    assert_eq!(v.assoc("d"), None);

    assert_eq!(v.mem_assoc("a"), true);
    assert_eq!(v.mem_assoc("d"), false);

    assert_eq!(v.remove_assoc("a"), Some(("a", 1)));
    assert_eq!(v.remove_assoc("d"), None);

    // keyに重複ありパターン
    let mut w = vec![("a", 1), ("b", 2), ("c", 3), ("a", 4)];

    assert_eq!(w.assoc("a"), Some(1)); // Some(4)ではない
    assert_eq!(w.assoc("b"), Some(2));
    assert_eq!(w.assoc("d"), None);

    assert_eq!(w.mem_assoc("a"), true);
    assert_eq!(w.mem_assoc("d"), false);

    assert_eq!(w.remove_assoc("a"), Some(("a", 1)));
    assert_eq!(w.remove_assoc("d"), None);
}

```
firebase-cloudStorageでの画像のアップロード

firebase-cloudStorageを使って画像の管理をしようと思い
ドキュメントをみてやってみたけどうまくいかなかった。
自分の見方が悪かった。。。

#修正後

```html
<template>
  <div id="images">
    <input type="file" accept=”image/*” @change="selectImage" value="画像追加" />
    <button @click="upLoad">画像追加</button>
  </div>
</template>
```

```javascript
<script>
import firebase from "../plugins/firebase";

export default {
  name: "images",
  data() {
    return {
      storage: firebase.storage(),
      image: "",
    };
  },
  methods: {
    selectImage(e) {
      e.preventDefault();
      this.image = e.target.files[0];
    },
    upLoad() {
      const storageRef = this.storage.ref().child(`images/${this.image.name}`);
      storageRef
        .put(this.image)//保存するファイル
        .then((snapshot) => {
          console.log("完了");
        })
        .catch(() => {
          console.log("エラー");
        });
    },
  },
};
</script>
```

#原因

```javascript
upLoad() {
      const storageRef = this.storage.ref().child(`images/${this.image.name}`);//ここ
      storageRef
        .put(this.image)
        .then((snapshot) => {
          console.log("完了");
        })
        .catch(() => {
          console.log("エラー");
        });
    },
```
const storageRef = this.storage.ref().child(`images/${this.image.name}`);
の部分の__.child__の部分をフォルダ名だけ指定したらいいと思っていて
__.child('images')__としていたのが原因でした。
調べてみるとフォルダ名と保存するファイル名が必要だったみたいです。
__.child()__の部分が保存場所ってことですね

#画像のURLの取得

```javascript
 methods: {
    selectImage(e) {
      e.preventDefault();
      this.image = e.target.files[0];
    },
    upLoad() {
      const storageRef = this.storage.ref().child(`images/${this.image.name}`);
      storageRef
        .put(this.image)
        .then(() => {
          storageRef.getDownloadURL()//ここを追加
          .then((url) => {
            console.log(url);//ここに画像のURL
          });
          console.log("完了");
        })
        .catch(() => {
          console.log("エラー");
        });
    },
  },
```
これで画像のURLも取得できるのでこれをfirestoreとかに保存したりしたら使えそうです。

無事解決！
アカウント作りました

# とりあえず
今までインプット用にQiitaを使っていましたが、アウトプットもしてくためにアカウントを作成しました。
何を書くかは今から考えます。。

# やっていること
ECサービスのバックエンド開発をやってます。

言語：Nodejs,PHP
サーバ：AWS,オンプレ
ツール：GitHub
などなど


はじめの一歩が悩む。。
よろしくお願いします！
ファイルのm行目〜n行目を抽出するスクリプト

headとtailを組み合わせれば可能。
組み合わせ方を一生覚えられないのでメモ。

```
cat hoge.txt | head -{n} | tail -{n - m + 1}
```

# 実例

```hoge.txt
1
2
3
4
5
6
7
8
```

2行目〜7行目を抽出

```
cat hoge.txt | head -7 | tail -6

2
3
4
5
6
7
```

# 応用

関数にしておくと素敵

```~/.bashrc
body(){
    cat $1 | head -$3 | tail -`expr $3 - $2 + 1`
}
```

```
body hoge.txt 2 5

2
3
4
5
```
派生サイトのWPから本サイトの記事を検索したい

# 派生サイトへの移行作業中にひっかかる
派生サイトを作っているときに、本サイトの記事を検索したり取得する必要が出てきた。
WP-USERを共有しているサイトなので、同一DB内。
tableのprefixが違うだけなので何とかならないか試したら出来たのでメモ。

# global $wpdbの値でprefixを入れ替える
## get_postのみ
コードは以下。
同一DB内、違うprefixのテーブルから記事を引っ張ってきている。

```php
global $wpdb; // 他のprefixのDBを参照する
$wpdbprefixbk = $wpdb;
$wpdb->set_prefix("wp1_");

$ref_post = ($refpid = $_GET["post_id"])? get_post($refpid): null;
// echo('<pre>'); print_r($ref_post); echo('</pre>');

$wpdb = $wpdbprefixbk; // 参照を戻す
$wpdb->set_prefix("wp2_");
```

## 検索クエリを発行する
検索クエリ発行するときもほぼ同様。最後に戻す。

```php
global $wpdb; // 他のprefixのDBを参照する
$wpdbprefixbk = $wpdb;
$wpdb->set_prefix("wp1_");

$paged = (get_query_var('paged'))? get_query_var('paged') : 1;
$args_base = array(
    'paged' => $paged,
);
$wp_query = new WP_Query($args_base);
?>
<div class="searcharea">
    <?php
    while ($wp_query->have_posts()) {
        $wp_query->the_post();
    ?>
        ~なんやかや~
    <?php } ?>
    <?php wp_reset_postdata(); $wpdb = $wpdbprefixbk; $wpdb->set_prefix("wp2_");// 参照を戻す ?>
</div>
```
[Rails] routingとmodelの命名規則が合わないときのaccepts_nested_attributes_forでハマる

# accepts_nested_attributes_for とは？

Railsで一つのフォームを使って、関連性のある親子レコードを楽に保存できる、非常に便利なメソッドです。
ggるとすぐ出てくるのですが、あまり評判はよくありません。

が、いずれにしても便利であるがゆえにサラリと親子レコードを作りたいときなどは使いたくなるのも心情です。
（そしてその中で少しハマってしまったので残しておこうと思います。）

ここでは基本的な `accepts_nested_attributes_for` の使い方は割愛します。


# 揃っていないroutingとmodelの命名規則

一般的にaccepts_nested_attributes_forを使う場合、viewファイルでは

```:_form.html.erb
<%= form_with model: @parent do |f| %>
  <%= f.text_fields :name %>
  <%= f.fields_for :children do |ff| %>
    <%= ff.text_fields :name %>
  <% end %>
  <%= f.submit '作成する' %>
<% end %>
```

といった形でformを作ります。


が、今回はmodelとroutingの命名が違うという状況だったため、

```ruby
# 利用したいmodel
class Parent

# Parentモデルを操作するroutes
resources :main
```

この状況で `form_with model: @parent` としてしまうと、
Railsの命名規則に則った形で処理しようとするため、`Routing Error`となります。

そういった場合、フォームを配置する際に、`form_with url: main_path` といった形でformの向き先をroutesに合った形で記載することになるのですが、

```:_form.html.erb
<%= form_with url: main_path, scope: :parent %>
```

としてしまったがばっかりに、formから渡されるデータ形式が合わずに、変にハマることになりました。


`form_with model: @parent` で書いた場合

```HTML:出力されるHTML
<input type="text" name="parent[children_attributes][0][name]">
```

```ruby:params(抜粋)
"parent" => {
  "name"=>"hoge",
  "children_attributes"=>{
    "0" => {
      "name"=>"hoge"
    }
  }
}
```

`form_with url: main_path, scope: :parent` で書いた場合

```HTML:出力されるHTML
<input type="text" name="parent[children][name]">
```

```ruby:params(抜粋)
"parent" => {
  "children"=>{
    "name"=>"hoge"
  }
}
```

といった形で、受け渡しが大きく変わり、複数の子レコードを作れない状態になります。
（なんなら想定していた形式と違いすぎてStrong Parametersで弾かれます）


## 結論

### routesとmodelの命名規則が合わない場合で`accepts_nested_attributes_for`を利用する場合は、

```:_form.html.erb
<%= form_with model: @parent, url: main_path do |f| %>
```

### modelを渡してあげるのが正解。

scopeで書いてしまうと、接頭語として使う文字列を指定するだけで、modelの階層構造なんてわからないので、当たり前といえば当たり前。
apacheアクセスログの400,500番台ステータスコードエラーを、時間範囲指定して抽出する

※　ログファイルが日付毎に分かれている、フォーマットはcombined_tsvを使用しているのが前提。

HH:MM:SS表記で指定したいので、時刻の箇所をsedを使用し独立させる。
ついでにIP末尾のポート番号も省いてしまう。
HH:MM:SSに開始時刻、終了時刻を指定することで、指定した時間内でステータスコードが
エラーコードとなっている行を抜き出す事が可能。

```ruby:qiita.rb
sed -r -e\ 's/(:[0-9]{4,5}|\/202[0-9]:)/ /'{,} /var/log/apache2/20200715/access_log | awk '"HH:MM:SS" <=$5&&$5<= "HH:MM:SS" {if($10>=400&&$10<=599)print $0}'
```

実際使ってみたところ、想定通り動いたが、時刻を編集するのが結構面倒だった。
ので、readで標準入力から時刻を変数に設定して、入力した指定時刻から現在までを
表示させることに。コマンドを実行すると入力画面になるのでHH:MM:SSのフォーマットで時刻を入力。
アクセスログのパスは適宜変更。

```ruby:qiita.rb
read -p "starttime? HH:MM:SS >" sTrttim && sudo sed -r -e\ 's/(:[0-9]{4,5}|\/202[0-9]:)/ /'{,} /var/log/apache2/20200715/access_log | awk -va=$sTrttim -vb=`date +%H:%M:%S` '{if($5>a&&$5<b&&$10>=400&&$10<=599)print $0}' ; unset sTrttim
```

ある程度出力を絞りたい場合、printする箇所を指定する。
下記ではIP別で数を集計し上位20を表示。
※アクセスログは最新のものを指定。下記ではyyyymmddディレクトリ内にアクセスログがある事を想定

```ruby:qiita.rb
read -p "starttime? HH:MM:SS >" sTrttim && sudo sed -r -e\ 's/(:[0-9]{4,5}|\/202[0-9]:)/ /'{,} /var/log/apache2/`date +%Y%m%d`/access_log | awk -va=$sTrttim -vb=`date +%H:%M:%S` '{if($5>a&&$5<b&&$10>=400&&$10<=599)print $10,$1}' | sort | uniq -c | sort -nr | head -20 ; echo "time range > $sTrttim - `date +%H:%M:%S`" ; unset sTrttim
```
CSSで見出しの文字を消したら謎の余白が出来た

まだコーディングに慣れておらず戸惑ってしまったので、備忘録として残します。

<h2>現象</h2>
HTMLは以下のように記述
`<h2><span class="hoge">文字</span></h2>` 

class「hoge」に囲まれた文字をCSSで消したところ、余白が出来てしまった。[^1]
他にh2を使用していた箇所<b>あり</b>。

<h2>検証</h2>
Chromeの検証ツールで確認。
spanを囲っているh2には何も余白をつけていなかったが、
他にh2を使用していた箇所があり、CSSで<b>要素そのもの</b>にmarginを設定していた。
そのため、文字は消えたがmarginだけ残ってしまった。

<h2>結果</h2>
他の要素内のh2にclass名を振ったところ、余白は消えた。

<h2>学び</h2>
きちんとclass名を付けましょう！

<h2>余談</h2>
Q. h2をspanで囲えばええやん！
A. h2はブロックレベル要素、spanはインライン要素なので出来ません。

<h3>参考リンク</h3>
[インライン要素 - HTML: HyperText Markup Language | MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Inline_elements "インライン要素 - HTML: HyperText Markup Language | MDN")


<br>


[^1]: 幅と高さを1pxにし、clipで切り抜いた。(<a href="https://shibajuku.net/" target="_blank">Shibajuku</a>のPCコーディング講座より)
【備忘】Spring BootでLogbackを使用する際の設定ファイル

備忘のためSpring BootにおけるLogback使用時の設定ファイルを以下に挙げる

```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />

    <!-- 標準出力はデフォルトのものを使用する  -->
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />

    <!-- 標準出力の出力パターンをデフォルトから変更する -->
    <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %t [%-5p] [%c] %m%n"/>

    <!-- ファイル出力をINFOとERRORで分けたいので別々に定義を行う -->
    <!-- INFOレベル出力用定義 -->
    <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<encoder>
            <charset>UTF-8</charset>
			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
		</encoder>
		<file>ログファイル名</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>ログファイル名.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
			<maxFileSize>10MB</maxFileSize>
		</rollingPolicy>
	</appender>

    <!-- ERRORレベル出力用定義 -->
    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- ERRORレベルのみ出力するようフィルタを定義する -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
          <level>ERROR</level>
          <onMatch>ACCEPT</onMatch>
          <onMismatch>DENY</onMismatch>
        </filter>
		<encoder>
            <charset>UTF-8</charset>
			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
		</encoder>
		<file>エラー用ログファイル名</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>エラー用ログファイル名.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
			<maxFileSize>10MB</maxFileSize>
		</rollingPolicy>
	</appender>

    <!-- INFOレベル以上を出力するようにする -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE_INFO" />
        <appender-ref ref="FILE_ERROR" />
    </root>
</configuration>

```
GitHubでの主な開発の流れ

#はじめに

最近、githubを使って開発する時の流れを聞かれることが多かったのそのことについて話していこと思います。

#目次
1. GitHubからclone
2. issueを書く
3. ローカル上でbranch作成
4. GitHubでPull Requestからmasterにマージ
5. さいごに

#GitHubからclone
チームで開発をしている時や、自分でリポジトリを作成した後はまず最初にローカル上にリモート上のリポジトリを持ってくるところからスタートします。

![aaaaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605875/4ba0cd25-f734-dd0c-0ee4-ebd1b21b715e.png)

GitHub上のリモートリポジトリの緑のCodeの部分を押すとこのような画面になるのでhttps://..から始まるURLをコピーします。(Download ZIPを押すとZIPファイルで落としてくることが出来ます)
コピーした後にローカル上でgitを開いてcloneします。今回は、[Git Bash](https://gitforwindows.org/)を使用します。

```
$ git clone リポジトリのURL名
```
これで、自分のローカル上にリモートのリポジトリを持ってくることが出来ました。

#issueを書く
次に、必要な機能や気になるバグなどを見つけた時には、issueに書くといったクセをつけるようにしましょう。ここの部分を直して欲しいと口頭で伝える人もいるのですが、そんな時もisseuで書いてと言うよにしましょう。
![aaaaaaaaaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605875/9fea33ef-d4c2-fd02-206c-33fd52ff01a7.png)

このようにissueはタイトルと詳細な内容を書くことが出来ます。タイトルは簡潔に分かりやすいように、詳細な内容は詳しく書きたいことがある時に書きます。
issueを書くと、下記の画像の**#番号**のような番号が発行されます。次のbranch作成の時に必要になってきます。![aaaaaaaaaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605875/a34cc9b8-5a18-6a9e-7e46-176fe72fef3d.png)

#ローカル上でbranch作成
issueを書いた後に、ローカル上で作業を進め機能を追加した後にリモート上にあげる作業に入ります。最初に、branchを作成します。

```
$ git branch ブランチ名
```

これでbranchが作成されます。また、branchの命名規則は先ほどのissue番号を使用するようにします。

`feature/#22_add_customer_delete`

featureは機能を追加するといった意味になります。また、hotfixはバグを修正するといった意味になります。#22は先ほどissueを書いた時に発行された番号を書きます。こうすることによりこのbranchはこのissueですよと結びつけることが出来ます。番号の後は、add,remove,updateなどの動詞を使用します。最後のcustomer_deleteは今回追加する機能を簡潔にし書きました。

```
$ git branch feature/#22_add_delete_customer
```
branchを作成した後は、add、commit、pushまでしてリモート上に自分が変更した内容をあげましょう。add、commit、pushに関しては[公式ドキュメント](https://docs.github.com/ja)の方で探して見てください。

#GitHubでPull Requestからmasterにマージ
リモート上にローカルで編集した内容を上げたので次にmasterにマージをする段階なのですがその前に、Pull Requestといった機能を使います。このPull Requestは、簡単に言うとマージの一歩手前の段階で他のチームメンバーにmasterにマージしたいからこれで大丈夫かといった確認を取ることが出来ます。また、コンフリクトが起こっているかなどマージする前に確認することが出来ます。
![aaaaaaaaaaaaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605875/4c580d52-a7f3-8bd1-b381-49a451d65df4.png)

緑のNew pull requestを押すと下記の画像が出てきてpull requestをしたいbranchを選択することが出来ます。現在はmasterからmasterになっていますが。変更して選ぶことが出来ます。
![aaaaaaaaaaaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605875/99721e38-d693-1406-8d4c-3e97f224f46c.png)

次にpull requestをすると下記の画面が出てきます。Merge pull requestを押すと選んだブランチにマージすることが出来ます。<font color="Red">(この時点でコンフリクトを起こすとマージ出来ないので注意する)</font>
![aaaaaaaaaaaaaaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605875/0bdae84b-d8db-559c-07b3-f8b98f30986e.png)


#さいごに
大体の流れは、こんな感じで良いのですが会社でやる時はその会社独自のやり方などもあるのでその時は会社のやり方に合わせましょう。また、有名なリポジトリのやり方なども真似するのもいいでしょう。


#参考文献
[gitのブランチの命名規則](https://qiita.com/luccafort/items/c91e817e78f1167221cc)
[【Git】ブランチの命名規則を調べてたらIssueドリブン開発という存在を知った](https://qiita.com/c6tower/items/fe2aa4ecb78bef69928f)
XcodeでSwiftの自動補完が効かなくなったら

XcodeでSwiftを書いているとまれに頻発する

* 自動補完が効かなくなる (文脈に応じた候補が出てこない)
* Refactor > Rename... でエラーが出る

などの問題をXcodeを再起動せずに直したい。

## 解消方法

(Xcode 11.6 で確認)

以下のコマンドで補完などに関わってるプロセスをkillして強制再起動すると直る。
(killすると自動的に再起動される)

```console
$ pgrep -f SourceKit | xargs kill
```

## 再起動するプロセス

* /Applications/Xcode.app/Contents/SharedFrameworks/SourceKit.framework/Versions/A/XPCServices/com.apple.dt.SKAgent.xpc/Contents/MacOS/com.apple.dt.SKAgent
* /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/sourcekitd.framework/Versions/A/XPCServices/SourceKitService.xpc/Contents/MacOS/SourceKitService
ヤベ！うっかり怪しいページ開いてセキュリティアラート出ちまった・・をなんとかしたい


# ウィルス対策製品ってなんなん？

　プログラミングで行き詰った時、海外ベンダー製品の仕様、知らない単語・・・
日々様々な目的で僕らはサーチエンジンで調査をします。その際に怪しいスクリプトが仕込まれたサイトを開いてしまってセキュリティアラートを出して情シスから入電喰らった事もあると思います。

### いや、絶対ありますよね？（瞬発力だけの推定）

実行ファイルで怒られるのは分かるんだ、だって確かに実行しようとしたもの・・

### でも、ページ開いたら怒られるのって注意しようがなくない？

DNSキャッシュポイズニングとかで**「XXXX人目おめでとうございます！YYが当選しました！！」**ページが開くやつとか。開く前に怪しいかどうかチェックできないと防ぎようがないじゃんよ。。

# つくってみたわ

<a href="https://github.com/yasutakatou/goScore"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/yasutakatou/goScore.png" width="460px"></a>

<a href="https://github.com/yasutakatou/goScoreExtension"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/yasutakatou/goScoreExtension.png" width="460px"></a>

事前準備：
折角チェックした結果が改ざんされたらたまらんので**HTTP通信必須**にしています。
よって、自己著名でも良いからSSL証明書が無い場合は*mkcert*あたりでサクっと作成してくださいな。

１．サーバー側準備

[実行ファイルをダウンロード](https://github.com/yasutakatou/goScore/releases)してきて動作させます。
スペースかリターンで今のIPと使ってるポートが出るので控えてください。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/fa550e59-793f-479d-837c-547334e1052b.png)

２．Chrome拡張をインスコ

こちらも[Gitのリリースページからダウンロード](https://github.com/yasutakatou/goScoreExtension/releases)してきてChromeに入れてください。

![2a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/28fe1ef0-c0de-e0e4-0eb0-55061273bffd.png)

拡張のアイコンをクリックして、先に控えたサーバーのIPとポートを入力します。
**（追加が成功したら下に登録されます）**

![2b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/d09771c5-030b-e63a-2d9d-befe69d179a5.png)

~~前回のリポジトリチェックと全く同じGUIという完全な手抜き~~

３．URLをチェックする

チェックしたいURLを右クリックするとコンテキストメニューに拡張機能のメニューが表示されるので選びます。

![3a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/a963a267-3a92-2988-d3fe-ac0cba95d5a4.png)

サーバーに問い合わせします。サーバー側でチェックして結果を返します。

![3b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/2a4f331d-5618-ca42-1b3d-afec70d04451.png)

星でスコアが表示されます。三つでガチ安全ですね。安全を確認したらリンク押して本来のURLを開きましょう。

![3c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/619b05d7-7523-1319-f45c-27311474ee45.png)

### ということで開く前に怪しいかどうかバッチリチェックできるようになりました！

ちな、キャッシュ機能があるので毎回チェックは走らないです。Go側にキャッシュにあれば前回チェック内容を踏襲します。

（その他、機能詳細はリポジトリ側にてご確認ください）

# あとがき

元々Chrome拡張だけで作ろうと思ってたけどfetchやらで証明書のチェックを
実装するのは相当難しいかんじだったのでAPIはいつも通りGo言語でいっかーって
開き直ったらトータル一週間で出来た！！

ここまでパッと書ける言語ガチで凄くね？

### サンキューGo言語！！
Jqueryまとめ１

<h1>基本的な記述方法</h1>
<p>$（'セレクタ').メソッド（引数）;
文字とかを消したり出したりする記述とは何か
メソッド部分のところに<font color="Red">fadeOut</font>で文字が消えるようになり
また<font color="Red">fadeIn</font>で文字が出てくるようにできる。

あらかじめ隠してる要素を表示させるには、<font color="Red">show()</font>を記述させると良い

<h2>イベントを起こしたいときの記述方法</h2>
<font color="Red">$('セレクタ').イベント名(ruction(){
//イベント発生処理
});</font>

クリックイベント
click(fuction(){
});

CSSメソッド
css('プロパティ名','値')

HTMLメソッド
html();
text();

<h3>thisの構文</h3>

<font color="Red">$(this)</font>イベントの中で、イベントが起こった要素を取得

<h4>変数を使う場合</h4>

宣言時　varを使用すしないとエラーになります
<font color="Red">var ＄title=$('#title')</font>

メソッドチェーン
同じJquerを複数回使用時に処理を高速化できる方法だよ
$（'セレクタ').メソッド（引数).メソッド（引数）
JS、TSの「?.」って何者か


## はじめに
TypeScriptのコードを書いていると予測変換で選択してEnterを打鍵したとき、IDEが勝手に以下の感じになったりする

```typescript
foo?.bar
```

今までほとんど使う場面がなかったために何なのか把握してなかったが、使っていた場面に出くわしたので、超初歩的な内容かもしれないが、備忘のために記事を投稿しようと思った
ちなみに`?.`はJSでもある

## そもそも名称は何なのか
オプショナルチェイニング演算子という名称らしい
当然初耳だし、今まで雑に「はてなドット」って呼んでました

## 挙動
オブジェクトのネストの深いプロパティにアクセスするときにnullishを確認せずにアクセスできるようになる
以下は使用例

```typescript
type A = {
	a?: {
		b: string;
	};
};

const a: A = { 
	a: {
		b: "hoge"
	};
};

// nullishを確認する場合
console.log(a.a ? a.a.b : undefined);
// => hoge

// オプショナルチェイニング演算子を使った場合
console.log(a.a?.b);
// => hoge
```

参考演算子での確認を省ける分簡潔になる
また、参照がnullishの場合には式が短絡評価され`undefined`が返り、それ以降は実行されない

余談だがnullishのときに返したい値を`undefined`以外にしたい場合は三項演算子を使わず以下のように書ける

```typescript
const b: A = {
	a: undefined
};

console.log(b.a?.b);
// => undefined

console.log(b.a?.b || "hogehoge");
// => hogehoge
```

関数や配列に対しても使える

```typescript
type B = {
	a?: string[];
	b?: (n: number) => number;
};

const c: B = {
	a: ["foo", "bar"],
	b: (n: number) => n + 1
};

// 配列
console.log(c.a?.[0]);
// => foo

// 関数
console.log(c.b?.(1));
// => 2
```

ドットのあとに括弧があるのに違和感を覚えるが、どうやらどんな型であれ`?.`の形は揺らがないっぽい

## おわりに
まあほとんど参考のリンクを読めばいいのだが、冒頭で述べた通り記事に残すことで頭に残りやすいということで投稿してみた
仕様を把握した限り、何故今まで使ってこなかったのかわからんくらいには便利な気がしている
今まですべて三項演算子等でnullishのチェックをしていたので、使える場面をしっかり見極めて、効果的に三項演算子と使い分けられるように戒めたい

## 参考
[Optional chaining - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining)
Goの依存パッケージ管理ツール dep と Go Modulesの違い

Go言語のパッケージ管理ツールのDepとModulesの違いについて調べた内容をここにまとめました。
少しでもご参考になれば幸いです。

# まず始めにGOPATHについて

Goを初めて触った頃に、困ったことがありました。それはパッケージの管理でした。
プライベートでの開発時のGOPATHの設定は`$HOME/go`して、参画していた案件に関しては`$HOME/hogehoge-project/go/`みたいな感じでGOPATHを分けていました。
分けていた理由としてはやはり依存しているパッケージのバージョンに違いなどがあったからです。

例えば

```sh
$HOME/go/src/github.com
go
└── src
    ├── github.com
    │   ├── my-github-repos
    │   │   ├── csv_sample
    │   │   ├── image_example
    │   │   └── test_code
    │   ├── codegangsta
    │   │   ├── envy
    │   │   └── gin
    │   ├── davidrjenni
    │   │   └── reftools
    │   ├── derekparker
    │   │   └── delve
    │   ├── fatih
    │   │   ├── gomodifytags
    │   │   └── motion
    │   ├── go-delve
    │   │   └── delve
    │   ├── golang
    │   │   └── dep
    │   ├── golangci
    │   │   └── golangci-lint
    │   ├── josharian
    │   │   └── impl
    │   ├── json_sample
    │   ├── jstemmer
    │   │   └── gotags
    │   ├── kisielk
    │   │   └── errcheck
    │   ├── klauspost
    │   │   └── asmfmt
    │   ├── mattn
    │   │   └── go-shellwords
    │   ├── mdempsky
    │   │   └── gocode
    │   ├── rogpeppe
    │   │   └── godef
    │   ├── stamblerre
    │   │   └── gocode
    │   └── zmb3
    │       └── gogetdoc

```
`go/src/github`配下に依存パッケージがインストールされます。
ここで問題なのが、`my-github-repos/csv_sample`と`other-github-repos/image_sample`でginというGoフレームワーク使っている場合、`~/go/src/github.com/codegangsta`を共通で利用するので、各々で異なるバージョンを指定できないのが問題でした。

こういった問題があるので、私はそのプロジェクト用にGOPATHを新たに作成していました。

```sh
# fish
set -x GOPATH "$HOME/go:$HOME/hogehoge-project/go"
```
Goを使用したプロジェクトが増えていくたびに、GOPATHも追加していくという悪循環に陥る。（個人的に好きじゃなかった）
しかも`go get`を使用すると、デフォルトでGOPATHを最初に指定したディレクトリにインストールされたりと、いろいろ面倒だったり。

# dep
当時（たしかGOのバージョンが1.10ぐらいの時）、パッケージのバージョン管理をどうしようかなっと思って、ググって調べました。そうするとGOのパッケージ管理ツールでDepというものに出会いました。
vendor配下にパッケージがインストールされて・・・・うんにゃらかんにゃら。
どの言語でもよくみるやつですね。「これは便利そう」というが率直な感想でした。

```
$ cd ~/go/src/github.com/hogehoge-project/gorm_sample/vendor
$ tree -d -L 2
.
├── github.com
│   ├── go-sql-driver
│   └── jinzhu
└── google.golang.org
    └── appengine
```

# Go Modules
Go 1.11から外部パッケージとしてGo Modulesが使えるようになりました。
Go Modulesが出てくるまでの依存パーケージ管理と言えば、dep一択だったかなと個人的には思ってましたが、depを使わずにこちらを使用されることが増えている印象を受けました。
実際にGo言語で開発していた案件に参画した時もDepを利用されていました。Goのバージョンも当時は1.10とかでしたね。

```
$ cd ~/go/src/github.com/hogehoge-project
$ go mod init
$ go get github.com/labstack/echo@v2
$ cd ~/go/pkg/mod/github.com/labstack
$ tree -d L 1
.
├── echo@v2.2.0+incompatible
└── gommon@v0.3.0
```

```
$ cd ~/go/src/github.com/fugafuga-project
$ go mod init
$ go get github.com/labstack/echo/v4
$ cd ~/go/pkg/mod/github.com/labstack
$ tree -d -L 1
.
├── echo
├── echo@v1.4.4
├── echo@v2.2.0+incompatible
├── echo@v3.3.10+incompatible
└── gommon@v0.3.0
```
上記のようにバージョン毎のリポジトリがインスールされる

そして各々のプロジェクトにある`go.mod`というファイルがモジュールを管理しており、
importする際はこの `~/go/pkg/mod/` 配下にあるモジュールを使うようになります。

# 最後に
最近よく、depからGo Modulesに移行されている記事が目立つようになってきました。
私自身もGo Modulesについて知ったばかりなので深く掘り下げた内容ではなく、ざっと簡単な説明にはなりましたが参考になれば幸いです。
AzureAD　シングルサインオン設定

１．AzureADとは
　Microsoftが提供しているクラウドサービスのひとつで、クラウドベースの認証サービスを提供します。

２．シングルサインオン概要
　一度認証を行うと他のシステムに再度認証を行わずにログインができるようになるシステムのことです。

３．作業目的
　AzureADで認証を行えば、連携しているシステム（例えばSalesforceやFacebookなど）にログインなしでアクセスができるようになります。
　AzureADでは簡単にSSOの仕組みが設定できます。

４．実装方法
　実装方法は大きく分けて以下の2つのステップがあります。
　・アプリケーションの登録
　・ユーザーのアクセス権限設定
　2つのステップの方法をFacebookを例にして見ていきましょう。
　
　４．１．アプリケーションの登録
　　①Azureポータル「エンタープライズアプリケーション」をクリック
　　![Azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/a58ec00f-ee1b-9a2f-edaf-205d38d593c5.png)
　　②「＋新しいアプリケーション」をクリック
   ![Azure2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/3ac6fa3d-10f6-cd6b-609b-421c3284f1c5.png)

　　③カテゴリは「All」で検索ボックスに「Facebook」と入力し、検索で出たFacebookをクリックし、追加ボタンをクリック
　　![Azure3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/1ab1128a-770c-0054-b265-1bd0204d8b6f.png)
　　④「２．シングルサインオンの設定」をクリック
　　![Azure4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/72f4ff35-0811-1c37-3495-f8d0846f2ace.png)
　　⑤今回は「パスワードベース」をクリック
　　![Azure5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/056e08b2-15ce-4f05-8a25-b34cf7bbf42b.png)
　　⑥「保存」をクリック
　　![Azure6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/468a3f3b-0315-ce37-43bb-8dfca2796351.png)

　　こちらでアプリケーションの登録は完了です。

　４．２．ユーザーのアクセス権限設定
　　①Azureポータル>エンタープライズアプリケーション>Facebookを開く
　　②ユーザーとグループをクリック
　　![Azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/b35d8c26-3777-0adb-5b24-710febbe0495.png)

　　③「＋ユーザーの追加」で割り当てるユーザーもしくはグループを追加し、最後に選択を押す
　　![Azure2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/096d82d5-387d-4104-08cd-85069cea0fe5.png)



　　④割り当てられたユーザーアカウントの「アクセスパネルアプリケーション」を開き、アプリに「Facebook」が追加されているので、クリックし、テストをする
　　![Azure4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699286/6ded0d3b-9aef-cf4b-bbd1-fa38dad202df.png)


　以上でシングルサインオンの設定は完了です。