OmniAICreator/Qiita-1.07M huggingface dataset:
javascriptによる並列処理

## 概要
普段javascriptを書いているとよく使う非同期処理（Promise）だが、言語仕様上(
シングルスレッドのため)非同期処理は処理の順番を変えているだけで厳密には同期処理のようだった。

ざっくり図

```
同期処理
実行→結果→実行→結果...

非同期処理
実行→実行→結果→結果...

並列処理
実行→結果...
実行→結果...
```

よくよく調べていると`Worker`オブジェクトを使用すれば並列処理ができるみたいなので試してみた

**Document**
- [Docs Worker](https://developer.mozilla.org/ja/docs/Web/API/Worker)


## ブラウサでの使用

※メインスレッド以外では、domの更新などができない 

```index.js
var worker = new Worker("./greeting-worker.js");

// データが送られてきたら発火
worker.onmessage = function (message) {
  console.log(message)
  // workerの停止
  this.terminate();
};

// Worker作成時かWorker実行中でエラーとなった場合に発火
worker.onerror = function (err) {
  console.error("onerror", err.message);
};

// データ送信
worker.postMessage("Hi");
```

```greeting-worker.js
// worker.postMessageが呼ばれたら発火
self.onmessage = function (message) {
  // 送られてきたデータ
  console.log(message);
  // workerにデータを送る
  self.postMessage("I'm good.");
};
```

## バックエンド(Node.js)での使用

```index.js
var { Worker } = require("worker_threads");
var worker = new Worker("./greeting-worker.js");
// データが送られてきたら発火
worker.on("message", function (message) {
  console.log(message);
  // workerの停止
  worker.terminate();
});

// Worker作成時かWorker実行中でエラーとなった場合に発火
worker.on("error", function (err) {
  console.error("onerror", err.message);
  // workerの停止
  worker.terminate();
});

// workerが停止したら発火
worker.on("exit", function () {
  console.log("Bye!!");
});

// データ送信
worker.postMessage("Hi, how are you?");
```

```greeting-worker.js
// worker.postMessageが呼ばれたら発火
self.onmessage = function (message) {
  // 送られてきたデータ
  console.log(message);
  // workerにデータを送る
  self.postMessage("I'm good.");
};
```


```js
// スレッドを増やしたい場合
var worker1 = new Worker("./worker1.js")
var worker2 = new Worker("./worker2.js")
var worker3 = new Worker("./worker3.js")
...
```

## 感想
あまり並列にすることもない処理でしたが、意外と簡単に扱うことができました。
使い所としては、処理が重い計算処理などやindexedDB(ブラウザ)があるそうです。
またワーカースレッドでデータをやりとりできる`MessageChannel`というのもありました。（他ArrayBufferやFileHandleというものもあった）


## まとめ
- javascriptは非同期処理の他に並列処理もできる
- ブラウザ/Node.jsともにAPIが用意されている.（使用感もほぼ同じ）
- メインスレッド以外では、domの更新などができない
- ワーカースレッドを増やしたい場合は複数Workerを呼び出す
- ワーカースレッド間でのデータのやりとりは`MessageChannel`を使用して行うことができる。
Ruby/FiddleのFiddle::Closure::BlockCallerはRubyのガーベッジコレクションから保護しないとダメ

タイトルのとおりです。

RubyからC言語を呼び出すFiddleライブラリでコールバック関数は `Fiddle::Closure::BlockCaller` を使います。

```ruby
Fiddle::Closure::BlockCaller.new(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP]){|x, y|
  x.to_s(1) <=> y.to_s(1)
}
```

ところが、`Fiddle::Closure::BlockCaller` はRubyのオブジェクトなので、気をつけないとガーベッジコレクションに回収されてしまいます。ガーベッジコレクションに回収されると、メモリが開放されてしまい、呼び出すことができなくなります。そしてSegmentation Faultが発生します。

Rubyでは関数の代わりにブロックがあります。ブロックを利用して、動的に`Fiddle::Closure::BlockCaller`のインスタンスを生成するということやりたくなるはずで、この際に注意してオブジェクトへの参照を残しておかないと、GCがせっかく生成した回収していきます。具体的には、レシーバのポインタのインスタンス変数に`Fiddle::Closure::BlockCaller`を追加してやるなどします。

普段Rubyを使う上で、GCやメモリ管理など考えないので、かなり注意していないと、この罠にはまります。

この記事は以上です。
トラックパッドは長く使用するように設計されていないかもしれないので注意が必要

(MacBook Pro 13-inch 2019を使用)

2020年はリモートワークという大きく環境の変化があった関係で、それまでマウスでの環境からマウスを全く使わないでトラックパッドを使う環境に変化した(トラックパッドにした理由はスタンディングデスクなど複数の場所の作業環境のため)。

4ヶ月〜半年くらいたった頃から指が痛くなる問題が発生。手袋を使ったり、テープを貼ったり皮膚科にも行ったが、最終的には普段の生活にも支障をきたすようになったし、爪が爪甲剥離のような見た目になってきたので、流石に使用をやめ泣く泣くマウスにすることにした。

一応かなり試行錯誤したのだが、それでもダメだったということは記事を書く意味があるのかなと思ったのでQiitaに書くことにした次第である。

使用していたのは基本的に仕事8時間の間で、主に作業内容はプログラミングである。




### やったこと

* トラックパッドに傷防止用のフィルムを貼る

    * 特に変わらなかったと思う。ちなみに、macbookのトラックパッドの表面はガラス製とのこと。複数の製品は試してないが、(ググったところ)摩擦係数はあまり差がないようである。

* クリーム(ワセリン)を塗る
    * 特に変化なし

* 痛くなったら左手で
    * 右手どうしても使っちゃう
    
* あかぎれ保護バンを痛いところに貼る
    * つけてると痛いのは防げるが、治っていく様子はない(ゆっくり悪化していたかも)
    * 医者に効果があるか聞いたがやはり治りはしないような返答

* 皮膚科で処方された薬デルモベートを塗る
    * 確かに塗っていたら良くなったが、気を抜くとすぐ悪化する感じ。 
    * 塗っていると防止効果もあるとのことだが、良くなった状態でも毎日丁寧塗るということは筆者の性格上うまくできなかった(強そうな薬を年間使用するというのも個人的にはためらった)。

* ビニール手袋
    * トラックパッドは使用できるが、1日中つけているとかなり蒸れてくるのでやめた(症状は回復したかどうか分からない)。
    * 数時間でバンバン捨てるという使い方はありかもと書いていて思ってきた。

* 手袋(東和コーポレーション)
    * いかにも作業用という手袋、長く使用すると反応が悪くなった。
    * これは手を守る感が強く良さそうだが、2本指の動作など反応が悪く結局使えず。

* 手袋(ニトリル製)
    * [これ](https://discussions.apple.com/thread/3653740)を参考に日本のものを買ってみたが、トラックパッドには効かなかった(スマホの画面はぎりぎり使えるくらい)

* 指先につけるやつ
    * これは反応は良いが1日作業するなかで、トイレ等でいちいちはめたり外したりは面倒。なくなりやすいのも問題で使わなくなった。


### 補足

* 筆者は汗っかきなタイプである。
* 冬になるつれ特に悪化したので乾燥は影響ありそうである。
* もしも、有効なやり方を知っている方がいましたら情報を下さい。
【Artifactory】Dockerリポジトリの使い方

# ArtifactoryのDockerリポジトリ
Artifactoryというリポジトリ管理サービスには様々なリポジトリタイプが使用可能ですが、今回はその中の一つであるDockerについて使い方を掲載します。
Dockerとはコンテナ仮想化のオープンソースソフトウェアの一つで、ソフトウェアやサービス単位で管理する事が出来ます。

## 事前準備
Dockerリポジトリを使用する為に、クライアント側にDockerをインストールする必要があります。
WindowsやMacでDockerを使用する場合は[こちらから](https://www.docker.com/products/docker-desktop)クライアントソフトをダウンロードします。
CentOS(Linux)では以下のコマンドを実行します。

```
yum install docker
```

インストール後に以下のコマンドでDockerを起動します。

```
systemctl start docker
```

Dockerの試用準備が完了したので、次はDockerのテスト用イメージ「hello-world」を取得(Pull)します。
取得には以下のコマンドを実行します。

```
docker pull hello-world

実行後以下のメッセージが表示されていれば完了。
Status: Downloaded newer image for docker.io/hello-world:latest
```

「hello-world」イメージの取得後、```docker images```コマンドを実行すると、以下の様な結果が表示されます。

```
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
docker.io/hello-world   latest              bf756fb1ae65        12 months ago       13.3 kB
```

## DockerリポジトリへイメージをPush
先程取得した「hello-world」イメージをArtifactory上のDockerリポジトリへPushします。
まずは以下のコマンドを実行し、対象のDockerリポジトリにログインします。

```
docker login <ArtifactoryのFQDN>

Username:<Artifactoryへのログインユーザー名>
Password:<Artifactoryへのログインパスワード>
```

ログインしましたら、DockerリポジトリへイメージをPushしますが、その前にPushするイメージにタグを設定します。
コマンドは以下です。

```
docker tag <対象dockerイメージID> <ArtifactoryのFQDN>/<Dockerリポジトリ名>/<対象dockerイメージ名>:<タグ名>

<対象dockerイメージID>は「docker images」コマンドで表示されたIMAGE IDを入力する。
<対象dockerイメージ名>はPush対象のイメージ名（今回の場合はhello-world）
<タグ名>は任意
```

タグを付けた後で再度```docker images```を実行すると以下の通りリポジトリが追加されています。

```
REPOSITORY                                            TAG                 IMAGE ID            CREATED             SIZE
docker.io/hello-world                                 latest              bf756fb1ae65        12 months ago       13.3 kB
<ArtifactoryのFQDN>/<Dockerリポジトリ名>/hello-world   <設定したタグ名>               bf756fb1ae65        12 months ago       13.3 kB
```

この状態でArtifactoryへpushします。コマンドは以下です。

```
docker push <ArtifactoryのFQDN>/<Dockerリポジトリ名>/<対象dockerイメージ名>:<設定したタグ名>

上記コマンド実行後に以下の内容が表示されたら完了。
Pushed
<タグ名>: digest: sha256:<省略>
```

## PushしたイメージをPull
先程Pushした「hello-world」イメージをPullします。
その前にクライアント上に残っているイメージを削除します。
イメージを削除するコマンドは以下です。アルファベットと数字の羅列で表記されているイメージIDで指定するという事に注意してください。

```
docker rmi <イメージID>

※上記コマンドで「hello-world」イメージを削除しようとしたら「Error response from daemon: conflict: unable to delete bf756fb1ae65 (must be forced) - image is referenced in multiple repositories」というエラーが表示されました。
その場合は「-f」オプションを追加して強制削除します。
※強制削除実行前に以下コマンドを実行して念の為削除対象のプロセスが起動されていないか確認します。
docker ps -a
```

```docker images```を実行してPull対象のイメージが表示されない事を確認しましたら、以下のコマンドからイメージのPullを行います。

```
docker pull <ArtifactoryのFQDN>/<Dockerリポジトリ名>/<対象dockerイメージ名>:<設定したタグ名>

実行後以下のメッセージが表示されていれば完了。
Status: Downloaded newer image for <ArtifactoryのFQDN>/<Dockerリポジトリ名>/<対象dockerイメージ名>:<設定したタグ名>
```

```docker images```を実行したら、以下の様な結果が表示されます。

```
REPOSITORY                                            TAG                 IMAGE ID            CREATED             SIZE
<ArtifactoryのFQDN>/<Dockerリポジトリ名>/<対象dockerイメージ名>   <設定したタグ名>               bf756fb1ae65        12 months ago       13.3 kB
```

以上でArtifactoryのDockerリポジトリの使い方は完了です。
Pimplイディオムをまとめてみる

# はじめに
* Pimplとは`pointer to implementation`の略
* C++でよく用いられるテクニック
* Pimplイディオムを使用すると以下を達成することができる
    * APIのインターフェースと実装の分離
    * コンパイル依存性の低減
* 本記事ではPimplイディオムについてまとめてみました

# Pimplイディオムの使い方
### Pimplイディオム使用前
* C++では通常、クラスのプライベートメンバをヘッダファイルに記述します
* 以下がその一例

```Example.h
class CExample
{
public:
    CExample();
    void func1();
    void func2();
private:
    void func3();
    void func4();
private:
    std::string data1;
    int data2;
}
```

* 上記のようにプライベートメンバをヘッダファイルにて宣言していると以下のような問題があります
    * **情報の隠蔽ができていない**
        * プライベートメンバが外部から見えてしまっています
        * APIの実装を変更した際にクライアントコードにも影響を及ぼす
    * **コンパイル時のファイル間依存関係の増加**
        * 実装の一部を変更、例えば「func5()というプライベートメンバ関数を追加」すると、このヘッダファイルExample.hをインクルードしているすべてのファイルを再コンパイルする必要があります

### Pimplイディオム使用後
* そこで、以下のようにPimplイディオムを使用します
    * ヘッダファイルにはパブリックメンバのみ開示し、実装ファイル(.cpp)にプライベートメンバを記述します(Implクラスのメンバ関数の実装部分のコードは省略してます)

```Example.h
class CExample
{
public:
    CExample();
    void func1();
    void func2();
private:
    class Impl;
    std::shared_ptr<Impl> pimpl;
}
```
```Example.cpp
class CExample::Impl
{
public:
    Impl();
    void func3();
    void func4();

    std::string data1;
    int data2;
}

CExample::CExample():pimpl(std::make_shared<Impl>()){}
```
* ここで、ヘッダファイルExample.h内にて、定義されていないクラスImplのオブジェクトをなぜ宣言できるのか？オブジェクトのサイズがこの時点では分からないのではないのか？
    * ポインタなので、サイズは4 or 8バイトで確定しているのでこの時点ではオブジェクトのサイズは分からなくてもよいので、前方宣言だけで十分

* Pimplイディオムを使用したクラスをしばしば「ハンドルクラス」と呼びます
* ハンドルクラスを使ったAPIのインターフェースの定義をどう書くのかを以下で述べます。

### ハンドルクラスの使用

* クライアントコードに影響を及ぼすため、APIのインターフェース部分は変更したくない
    * 上記の例でいうと`func1`と`func2`は変更したくない

* Implクラス内でそれぞれのインターフェースに対応する実装用の関数を用意して、その関数に実装を委譲する
* 以下のコードが実装例です(Implクラスのメンバ関数の実装部分のコードは省略してます)

```Example.cpp
class CExample::Impl
{
public:
    Impl();

    //下記2つが、インターフェースに対応する実装用の関数
    void func1();
    void func2();

    void func3();
    void func4();

    std::string data1;
    int data2;
}

CExample::CExample():pimpl(std::make_shared<Impl>()){}

//実装に変更があっても、以下の2つの関数は変更されません
void CExample::func1()
{
    pimpl->func1();
}

void CExample::func2()
{
    pimpl->func2();
}
```
# Pimplイディオムのメリット
* **APIのインターフェースと実装の分離**
    * APIは情報の隠蔽をして、いかにクライアントコードへ影響を及ぼさないかが重要となる
    * Pimplイディオムを使用すれば、実装の変更をしてもクライアントコードへ影響が無くなる
* **コンパイル依存性の低減**
    * Pimplイディオムを使用すると、ヘッダファイルに記述されるのはAPIのインターフェース部分のみとなります
    * 実装を変更してもクライアントコードを再コンパイルする必要は無いです

# Pimplイディオムのデメリット
* 間接参照のオーバーヘッドが増える
    * 全メンバにアクセスする際には、ポインタの間接性一つ分回り道をすることになるので、パフォーマンスが低下する可能性があります

# 参考
* [C++のためのAPIデザイン](https://www.amazon.co.jp/C-%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEAPI%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3-%E3%83%9E%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%83%BB%E3%83%AC%E3%83%87%E3%82%A3/dp/4797369159)
* [Exceptional C++](https://www.amazon.co.jp/Exceptional-C-%E2%80%9547%E3%81%AE%E3%82%AF%E3%82%A4%E3%82%BA%E5%BD%A2%E5%BC%8F%E3%81%AB%E3%82%88%E3%82%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E5%95%8F%E9%A1%8C%E3%81%A8%E8%A7%A3%E6%B3%95-%E2%80%90Depth/dp/4894712709)
イベントカメラっぽい画像処理してみた

#概要

イベントカメラっていうカメラがあります。
このイベントカメラ風に通常動画を変換してみたいと思います。
なんかに使えないかな〜。

#成果物

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">イベントカメラ風映像 <a href="https://t.co/MFAUwzrdJt">pic.twitter.com/MFAUwzrdJt</a></p>&mdash; itdk (@itdk1996) <a href="https://twitter.com/itdk1996/status/1345635219810832384?ref_src=twsrc%5Etfw">January 3, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

動画はなんでもよかったんですが、固定カメラだときれいにとれます。今回は[GolfDB](https://github.com/wmcnally/golfdb)のデータからタイガーウッズのショットをやってみました

#イベントカメラとは

イベントカメラは、一般的なカメラと根本的に仕組みが異なります。
一般的なカメラは、ある高さH、ある幅W、RGBのどれかCからH×W×Cの次元の数値を持ちます。
動画であれば、(T×H×W×C)になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404462/fc17213f-87d3-77f3-b17f-f3fdc7d089a5.png)


一方で、イベントカメラは、あくまでイベントしか記録しません。ここで、イベントとは、「輝度値の変化」です。つまり時間方向で見て輝度値が閾値以上変化した「点」だけを記録していきます。記録するのはT×(X,Y,P)です。Pは輝度値が増えたら1、減ったら-1が入ります。変化がないところは記録されないのが特徴です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404462/c6a32de2-e6fe-474a-a760-393d366a4d0a.png)

#イベントカメラの特徴

さて、イベントしか記録しないこのカメラですが、以下のような特徴があります。

・超高フレームレート
・低消費電力
・非同期的

普通のカメラが60FPS程度なのに対し、イベントカメラは1000FPSを超えていきます。RGBカメラでは、FPSをあげるほど、カメラに入ってくる光の量が減って暗くなってしまうなどありますが、イベントカメラは入ってくる光の量が変わるか変わらないかなので高いFPSを保てます。
記録するデータが少ないので、低電力です。また、通常のカメラでは0.03秒目で1F、0.06秒目で2Fと一定のペースを開けてデータがありますが、イベントカメラの場合は
0.0012秒目で(100,200)で変化あり
0.0581秒目で(250,50)で変化あり
と変化があった時間でだけ記録されていきます。

低電力で高い時間分解能をもつことから自動運転などにも応用が考えられます。

#本題
簡単なコードですが、イベントカメラっぽいことをやってみます。
動画で変化があったフレームだけを残してみます。

本当は「差分のあった点だけを取得する」のがイベントカメラの本質的なデータ構造です。
np.where使うと簡単にその形式に変換できます
イベントカメラは一般的に点群データ形式です。なので時間方向で点を集計して可視化することが多いので、画像からその可視化映像っぽいのだけ作ってみます。

#コード
今回は１画像前の各チャネルで差分をとって閾値以上の場合はイベントとして画素を残します

```
import numpy as np
import cv2

def img2event_image(base_img, img, th = 10, plus = 128, minus = 255):
    img3 = base_img.astype(float) - img.astype(float)

    index1 = img3 > th
    img3[index1] = plus

    index2 = img3 < -1 * th
    img3[index2] = minus

    img3[~(index1) & ~(index2)] = 0 
    return img3.astype(np.uint8)

def video2event_video():
    stack = True
    path = "96.mp4"
    # output_name = "output.mp4"
    output_name = "output_stack.mp4"

    cap = cv2.VideoCapture(path)
    fourcc = cv2.VideoWriter_fourcc(*"mp4v")
    w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

    if stack:
        w *= 2
    fps = cap.get(cv2.CAP_PROP_FPS)
    fps = 30
    out = cv2.VideoWriter(output_name, fourcc, fps, (w, h)) 

    success, image = cap.read()
    # image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    base_image = image[:]
    while success:
        b_img = img2event_image(base_image.copy(), image.copy())
        if stack:
            b_img = cv2.hconcat([image, b_img])

        out.write(b_img)
        base_image = image[:]
        success, image = cap.read()
        # image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    cap.release()
    cv2.destroyAllWindows()
```

#参考

イベントカメラ DAVIS346
https://nanoxeed.co.jp/product/eventcamera/

イベントカメラの話
https://qiita.com/minomonter/items/6d71029f6c860da60740
dartメモ

#Generics 
List<>とかの<>のこと。
型を指定するために記載する。

##基本
```dart
void main() {
  List primeNumbers = new List.from([]);
  primeNumbers.addAll([2,3,5,7]);
  print(primeNumbers);
}

>>>[2, 3, 5, 7]
```

##intとstring混ぜる
```dart
void main() {
  List primeNumbers = new List.from([]);
  primeNumbers.addAll([2,3,5,7]);
  
  var person ={
    'name' : 'morimori',
    'age': '24',
    'height':'175',
  };
  primeNumbers.add(person);
  print(primeNumbers);
}

>>>[2, 3, 5, 7, {name: morimori, age: 24, height: 175}]

```

##＜int＞とするとintしか受け付けない
```dart
void main() {
  List<int> primeNumbers= new List.from([]);
  primeNumbers.addAll([2,3,5,7]);
  
  var person ={
    'name' : 'morimori',
    'age': '24',
    'height':'175',
  };
  primeNumbers.add(person);
  print(primeNumbers);
}

>>>error
The argument type 'Map<String, String>' can't be assigned 
to the parameter type 'int'

```
Ruby ディレクトリ内のファイルロックを試す

フルコードは以下。
[ディレクトリ内ファイルロックを試すRubyプログラム - sun610.web.fc2.com](https://sun610.web.fc2.com/program/c0001.html)

ポイントは

- File::LOCK_EX|File::LOCK_NB を使うこと ([参考](https://docs.ruby-lang.org/ja/latest/method/File/i/flock.html))
- Dir.globのアスタリスクの仕様
Amplify initが失敗する

#なにがおきたか

`amplify init --appId my-app-id`したら

```
Failed to fetch Amplify Admin credentials init failed
Error: TypeError: Cannot read property 'idToken' of undefined
    at Object.getAwsConfig (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-provider-awscloudformation/src/configuration-manager.ts:725:13)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
```

で死んだ。

公式の手順(https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/module-two/)通りなのに落ちた

#なおしかた

`amplify cli`のバージョンによるものらしい

https://github.com/aws-amplify/amplify-adminui/issues/32

一旦アンインストして、再度無事なバージョンを入れる

```
npm remove -g @aws-amplify/cli
npm install -g @aws-amplify/cli@4.36.2
```

無事にinitできた

これが`close`されたらバージョンあげよう...
Jestでクラスインスタンスの比較をすると、"Received: serializes to the same string" と出てきて必ずテスト結果がFAILになる。

# 発生している問題
Jestの`expect().toEqual()`でクラスインスタンスを比較すると、フィールドの値が同じでも何故かテスト結果がFAILになってしまう。

## テストコード
```
class Person {
  constructor(public readonly name: string, public readonly age: number) {}

  public greet = (): string => `${this.age}歳の${this.name}です。`
}

it('クラスインスタンスが一致している。', () => {
  const taro1 = new Person('taro', 20)
  const taro2 = new Person('taro', 20)

  expect(taro1).toEqual(taro2)
})
```

## テスト結果
```
 FAIL  src/tests/redux/scoreHistory/reducers/addNotes.test.ts
  ● クラスインスタンスが一致している。

    expect(received).toEqual(expected) // deep equality

    Expected: {"age": 20, "greet": [Function anonymous], "name": "taro"}
    Received: serializes to the same string

      56 |   const taro2 = new Person('taro', 20)
      57 | 
    > 58 |   expect(taro1).toEqual(taro2)
         |                 ^
      59 | })
      60 | 
```

インスタンスのフィールドは全て同じだが、テスト結果はFAILになってしまっている。

# 解決策
以下のように、比較するインスタンスを`JSON.stringify()`で囲ってあげたらテストが通るようになった。

```
// 省略

it('クラスインスタンスが一致している。', () => {
  const taro1 = new Person('taro', 20)
  const taro2 = new Person('taro', 20)

  expect(JSON.stringify(taro1)).toEqual(JSON.stringify(taro2))
})
```

これでいいのか？と、疑問を持ちつつも、明確な問題点が思いつくわけでもなく、テストも正しく行えているのでとりあえずいいだろう。

# 備考
解決するまでの過程で色々試した結果、クラスのメソッドを全部コメントアウトすると`JSON.stringify`で囲まなくてもテストが正しく通ることが分かった。
今回の解決策には関係ないが、もしちゃんと解決するなら役に立つ情報かもしれない。
Sidekiq-limit_fetchが仕事しない

ruby on railsの開発において並列処理の実行数を管理したかったが、うまくいかなかったのでその原因のお話

# Sidekiq-limit_fetchとは
Sidekiq-limit_fetchはsidekiqでの並列処理の実行数を管理するためのgemです。

https://github.com/brainopia/sidekiq-limit_fetch


```ruby:Gemfile
gem 'sidekiq-limit_fetch'
```

```ruby:sidekiq.yml
:queues:
  - queue1
  - queue2

:limits:
  queue1: 2
  queue2: 5
```

上記の場合、queue1は並列実行可能数が2、queue2は並列実行可能数が5となります。

# Sidekiq-limit_fetchが仕事しなかったお話
上記のようにsidekiq-limit_fetchのgemを使用しているにも関わらず並行実行数が指定数を超えることが起きました。

この原因としては他のgemによるlimitの設定関数のオーバーライドでした。

```ruby:Gemfile
gem 'serverspec'
```

上記のgemが原因でSidekiq-limit_fetchに記載されたset関数が正常に処理されませんでした。
serverspecはサーバーのテストを自動化するためのgemです。
そのため、serverspecをGemfileから削除することでsidekiq-limit_fetchは仕事をしてくれるようになりました。

しかし、並列実行数が稀に超過する現象は引き続き発生したため、自身でジョブの実行数を管理するコードを書く方が安全だということがわかりました。
【swift5,CocoaPods】同じライブラリが２つinstallされてたら、最初からやり直しましょう

#はじめに
`CocoaPods`にて、既にライブラリが入ってる状態で、更にライブラリを追加すると遭遇しうる不具合です。
（筆者は既に`FireBase`系のライブラリが入っている状態にて、２回遭遇しました。）

Error文としては`35 duplicate symbols for architecture x86_64`とかが出ると思います。

解消方法だけ知りたい場合は「解決策」まで飛ばしてください。

#筆者の遭遇した状況
開発初期に、ターミナルから以下のライブラリを導入。

 ```
pod 'IQKeyboardManagerSwift'
pod 'Firebase/Analytics'
pod 'Firebase/Auth'
pod 'Firebase/Firestore'
pod 'Alamofire'
 ```

###１回目の遭遇
ターミナルにて`pod update`を実行した直後。
提出先より「ビルドできない」との連絡があり発覚。

###２回目の遭遇
アプリにオンボーディングを実装するため、

```
pod 'Onboard'
```
を導入。
`pod install`後前回の不具合を思い出し、`Pods`ファイルを確認したところ発覚。

#エラーの原因


当該プロジェクトの`Pods`ファイルを確認してみると、画像のように名前の後ろに「２」が付いているファイルが出てくると思います。
![スクリーンショット 2021-01-03 16.32.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/881110/bbf8f471-d935-27c5-f1d0-ea3db9bdb185.png)
「２」が付いているファイルが１つ２つならまだしも、ご覧の通り滅茶苦茶ありますね。
これが今回のErrorの原因です。


#解決策
１つ１つダブっているファイルを消していくやり方だと、面倒な上にエラーが起きます。

単純ですが、`pod install`からやり直しましょう。


###手順① プロジェクトにアクセス
Finderやターミナルを使ってプロジェクトにアクセスしましょう。

####※バックアップを取っておくのも忘れずに
プロジェクトの上で右クリック。「”（アプリ名）”を圧縮」を選んで`zip`形式のバックアップをとっておきましょう。
Githubなどの管理ツールを使ってる方は、そちらででもいいですね。


###手順② 「`Podfile.lock`」と「`Pods`」を削除
プロジェクト下にある<font color='red'>「`Podfile.lock`」と「`Pods`」のみ削除</font>しましょう。

なお、`Podfile`は消さないように注意。
もし消しちゃったらゴミ箱から漁って戻すか、ターミナルで`pod init`して再作成しましょう。

###手順③ ライブラリを再インストール
ターミナルを開いて、プロジェクト下に移動してから`pod install`。
ライブラリの再インストールが始まるので、終わったら`xcworkspace`から開いて完了です。


#最後に
このエラーは、同プロジェクトに対する２回目のライブラリ導入が、`pod install`か`pod update`かに関わらず発生し得ます。

この不具合が起きてても、自身の開発環境では普通にビルドが通るので気付きにくいんですよね。
他人にプロジェクトを渡したときにはじめて気づくので、滅茶苦茶焦ると思います。

消して再インストールすれば簡単に治るので、落ち着いて処理しましょう。


###参考文献
 - [Cocoapodsでライブラリをアップデートしたらエラーが出たときの対処法｜タノモク｜note](https://note.com/antiphase/n/n36438a8db0f6)
JavaScriptのわかりずらかったことメモ

Javascriptでわかりずらかったことのメモです。

##可変引数
```javascript:コード
function test(...args) {
    console.log(args);
}

test("1", "2");
```

```text:結果
[ '1', '2' ]
```


##論理演算子と代入
```javascript:コード
var a = "1";
var b = "2";

var c = a && b;
console.log(c);

var d = a || b;
console.log(d);
```

```text:結果

2
1
```

a && bは!a ? a : b; と同じ。
a || bはa ? a : b; と同じ。

こちらを参考
https://qiita.com/masakazu_ca/items/3ce9228a6c009499cb79

##キーの名前でメソッド的

```javascript:コード
var map = {a:"1"};
console.log(map.a);
```

```text:結果
1
```
##変数名がキー名になる

```javascript:
var b = "2";
console.log({a:"1",b});
```

```text:結果
{ a: '1', b: '2' }
```
##ドット三つの奴を使う


```javascript:ドット三つを使うコード
var b = {'B': { "C": 'Cのvalue', }};
console.log({a:"Aのvalue",...b});
```
```text:結果
{ a: 'Aのvalue', B: { C: 'Cのvalue' } }
```

ドット三つの奴を使わないと

```javascript:ドット三つを使わないコード
var b = {'B': { "C": 'Cのvalue', }};
console.log({a:"Aのvalue",b});
```

```text:結果
{ a: 'Aのvalue', b: { B: { C: 'Cのvalue' } } }
```

##letとvarの違い


varは再宣言可能
letは再宣言不可

```javascript:varのコード
var a = "1";
var a = "2";

console.log(a);
```


```text:結果
2
```


```javascript:letのコード
let a = "1";
let a = "2"; // letで宣言された変数名はスコープ内に一つだけ

console.log(a);
```


```text:結果
ERROR:
let a = "2";
    ^
```

こちらを参考。
https://qiita.com/y-temp4/items/289686fbdde896d22b5e
XAML 系（WPF、UWP、Xamarin.Forms）で Binding でハマらないようにするために気を付けていること

XAML 系のプラットフォームで開発するときによくお世話になるデータバインディングですが、個人的に開発中にはまらないために気を付けていることを紹介しようと思います。

## 間違えないために

ハマらないために気を付けることは、Visual Studio に書いてもらうことです。これが一番大事です。人がプログラムを書くから間違えるので、なるべくツールに書いてもらいましょう。

データバインディングのパスでも同じで　Visual Studio が DataContext の型を認識できるようにするとインテリセンスが効きます。Visual Studio に書いてもらうことが出来ます。

例えば Windows Template Studio で適当に新規作成したプロジェクトの DataTemplate の Binding でインテリセンス出してみるとこんな感じになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/269b279f-b126-8bf8-dc7b-1633c3ae046e.png)

こんな状態だと、心の目でバインドのパス書かないといけないですね。これはよくないです。
こうならないためにデザイナーに DataContext の型を教えてあげる必要があります。

## DataTemplate の場合

DataTemplate の場合は DataType に型を指定するとデザイナーが型を認識してインテリセンスでプロパティ名を出してくれるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/240bf9d8-628a-9e19-42ca-05c0fea3f2ed.png)

## DataTemplate 以外の場合

`d:DataContext` で型を指定してやるとインテリセンスがきくようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/c1e8147e-c8de-0955-f3d2-7375dcbb247a.png)

## その他

### ライブビジュアルツリーとライブプロパティエクスプローラー

一応中身見れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/7003b1a0-857a-60ac-5aa5-c60eef730a9f.png)

ReactiveProperty を使ってるときに間違えて `.Value` を忘れたものを見ると、こんな感じに見えます。ReactiveProperty の ToString の結果には型名がないのでちょっとわかりにくいですが…。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/cb727eaf-b852-b899-5c3f-dbd290d7decb.png)

### データバインディングのパスを間違えたら

それでも間違えることはあります。例えば Title とうつところを以下のように TiTle としてしまった場合…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/6e1edb5a-1b23-394d-1207-ba7077e0ad12.png)

最新の Visual Studio だとこんな風にエラーがあると教えてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70288/ba40dba0-1586-8914-a0e7-64052c63f743.png)

前まではデバッグ実行時の出力ウィンドウに他のデバッグログに混じってこっそり出てたメッセージですが、これでとても見やすくなりました。

ただ、これは Xamarin.Forms には来てないかな？

## まとめ

色々便利機能はありますが、基本的にプログラムは人がタイプすると間違えるのでインテリセンスを出すようにひと手間かけてから書くとハマる可能性が減ります。その対策をしたうえで、もしハマってしまった場合はデバッグ系の機能に頼りましょう。

以上です。
Python dict でキーがなかったらデフォルト値を返すメモ

パラメータなどを dict で扱っている.


パラメータ定義(キー)がなかったらデフォルト値を返すようにしたい.

```py
val = None # Set default
if 'filename' in config:
    val = config['filename']
```

や, one liner で

```py
val = config['filename'] if 'filename' in config else None
```

という書き方があるが, ややこしい.

## get を使う

get の第二引数でキーがなかった場合のデフォルト値を設定できました!

```py
val = config.get('filename', None)
```

わかりやすいですね!
USB メモリから起動して macOS Big Sur を クリーンインストールする

# USB メモリから起動して macOS Big Sur を クリーンインストールする

## 手順

### 起動可能な USB メモリの準備

https://support.apple.com/ja-jp/HT201372 によると 12GB 以上の USB メモリが必要

1. 動作している mac で https://apps.apple.com/jp/app/macos-big-sur/id1526878132?ls=1&mt=12 から `macOS Big Sur` をダウンロードする
2. USB メモリを挿して、ディスクユーティリティを起動する
3. `Mac OS 拡張` 形式でフォーマットする。(このときに指定する ボリュームの名前 を `createinstallmedia` の引数で使う)
4. `sudo /Applications/Install\ macOS\ Big\ Sur.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume` (`MyVolume` は 3 で指定した `ボリュームの名前` に対応する)
 
### 作成した USB メモリからクリーンインストールする

この手順は Intel Mac の場合です。
Apple Silicon の場合は、 https://support.apple.com/ja-jp/HT201372 を参照

1. 作成した USB メモリを挿して、Option キーを押しながら、起動する
2. 起動ドライブを選択する画面になるので USB メモリを選択する。
3. ディスクユーティリティでディスクを消去する (参考: https://support.apple.com/ja-jp/HT208496)
4. macOS を再インストール を選んでインストールする。

## リンク

macOS Big Sur
https://apps.apple.com/jp/app/macos-big-sur/id1526878132?ls=1&mt=12

macOS の起動可能なインストーラを作成する方法
https://support.apple.com/ja-jp/HT201372

Intel 搭載モデルの Mac を消去する方法
https://support.apple.com/ja-jp/HT208496
緯度経緯をURLへ変換するサービス、マップクリエイター

<a href="https://figreen.org/mc/" target="_blank">マップクリエイター</a>とは、どんなWebサービスですか？
Googleマップの任意の地点をWebページ化するサービスです。場所をWebページ化することで空間にテキストが紐付くので、検索サイトから検索した時スムーズにその場所がどこにあるのかが、日本国民全員に分かるようになります。

<a href="https://figreen.org/mc/" target="_blank">マップクリエイター</a>を作ろうと思ったきっかけは何だったのでしょうか？
旅行に行った時よくバスをよく利用するのですが、田舎のほうになるとバス停がどこにあるのか分からなかったり、バス停が分かってもどのバスがどこへ向かうのかが分からないことが多々あったので、それを上手い具合に解決したいと思って作りました。

そこで、ITとかにあまり詳しくない人でも、特定の場所に対して簡単にテキストを埋め込めるサービスがあれば、Googleで検索した時にその場所の詳細がすぐ分かるだろうと思って作りました。

バス停だけにとどまらず、地元の名所やつっこんだ観光案内(雑学など)を書けば、地域復興にも繋がるかなと思います。

機能面でこだわった点などありますか？
Google マップでは場所によっては緯度経緯が表示されず、プラスコードというアルファベットだけの表示になることもあるので、プラスコードにも対応させました。また悪用防止のため、作成したページを削除する機能も付けました。

(<a href="https://figreen.org/mc/" target="_blank">マップクリエイター</a>は2018年に作ったwebサービスです)
Reactでいい感じのサブウィンドウを実装する  ⑤  初期表示の設定方法


シリーズ記事です。
初めての方は、[こちら](https://qiita.com/aokisinn1192/items/dd5f2598aef88d5a824f) を最初に読んでください


今回は、Reactでサブウィンドウの初期表示の設定方法について説明していきます。

# やり方

Rndのdefaultプロパティに値を指定してあげると指定した箇所に表示することができます

## 例1 画面の真ん中にサブウィンドウを表示する

```javascript
<Rnd
  default={{ 
    x: document.documentElement.clientWidth / 2, 
    y: document.documentElement.clientHeight / 2
  }}
>
  test
</Rnd>
```

## 例2 画面の右上に表示する

```javascript
<Rnd
  default={{ 
    x: 0, 
    y: 0
  }}
>
  test
</Rnd>
```

# おまけ
defaultプロパティにwidthとheightを指定すると、　サブウィンドウの初期表示時のサイズを調整できます。
## 例

```javascript
<Rnd
  default={{ 
    x: 0, 
    y: 0,
    width: 200,
    height: 100
  }}
>
  test
</Rnd>
```

## 
# 最後に

今回は、サブウィンドウの初期表示の設定方法について説明しました。

最後まで読んでよかったらLGTMお願いします！

[まとめ記事](https://qiita.com/aokisinn1192/items/32ade691b0fc60dedef0) もあるのでよければこちらもみてください
Firebase Cloud Functions 特定の関数だけをデプロイする方法

#関数のデプロイ方法は２つある
Firebase Cloud Functionsの初心者だった僕は、毎回`firebase deploy --only functions`を実行してたが、よくよく調べるともっと良い方法がありました:sweat_smile:

毎回全ての関数をデプロイしてたら非効率です。。。

プロジェクトの`functions`フォルダに移動してデプロイコマンドを実行するとき、主にコマンドは２つあります！

##全ての関数をデプロイ

```console
firebase deploy --only functions
```

すべての関数が同時にデプロイされます。

##特定の関数のみデプロイ

```console
firebase deploy --only functions:addMessage
```

```typescript:functions/src/index.ts
exports.addMessage = functions.https.onRequest(async (req, res) => {
  res.send('テスト実行した');
  // do something
});
```

これなら`addMessage`という関数のみがデプロイされます。


#参考
https://firebase.google.com/docs/functions/manage-functions
WSL環境でReact Nativeのホットリロードが動作しない場合

# 環境
* Windows 10
* Ubuntu 18.04.5 LTS
* npm 6.14.9
* expo 4.0.17
* Visual Studio Code 1.52.1

# 現象
Windows Subsystem for Linux (WSL) の **/home/{ユーザー名}** 配下に React Native プロジェクトを作成。
Visual Studio Code でプロジェクトを開き、Project/App.js を変更して保存しても、ホットリロードが動作しない。
ターミナルで直接 App.js を編集すると、ホットリロードが走る。

# 原因
Visual Studio で下記のディレクトリパスを参照していたため、ファイル変更の監視システムが動作していなかった。

```
C:\Users\{Windowsのユーザー名}\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home\{WSLのユーザー名}\work\reactnative\Project
```
下記のパスでプロジェクトを開けば解消した。

```
\\wsl$\Ubuntu\home\{WSLのユーザー名}\work\reactnative\Project
```

# 参考
下記の記事を参考にさせていただきました。ありがとうございました。
WSLとwindows間のファイル連携
https://qiita.com/quzq/items/1096c638c0d86795be13
【フロントエンド学習①】フロントエンドとバックエンド

# これは？

フロントエンドの学習をして、その理解のアウトプットとして作りました。
初学者にもわかりやすい文章を心がけます。
理解に間違いがありましたら、ご指摘いただけると幸いです。

# フロントエンドとは
主にHTML、CSS、JavaScriptで構成されている
サーバーとの通信や、ブラウザに表示されるもの

- HTML・・・規則に則ってコンテンツを記述する
→文章、画像、動画、など

- CSS・・・HTMLで記述されたものにデザインを付与する
→文字や画像の色や大きさ、コンテンツの配置、など

- JavaScript・・・ページに機能を持たせる場合に使用する
→ボタンを押した時の動作、サーバーとの通信の定義、など
→ブラウザ上で動作する<font color="red">ほぼ唯一の</font>プログラミング言語！<font color="red">（ここ重要)</font>
→ライブラリやフレームワークが豊富(jQuery、Bootstrap、React.js、Vue.js、Node.js、など)


# バックエンドとは
フロントエンドと比べて、使用できる言語は多い。(PHP、Java、Python、Ruby、など)
大きく「静的メージ」と「動的ページ」に分けられる

- 静的ページ
→リクエストに応じて__サーバーに用意されているファイル__を返却、ブラウザに表示される

- 動的ページ
→リクエストに応じて__サーバーにあるプログラムがページを生成__して返却、ブラウザに表示される


おわり
【Android】環境構築①【備忘】

1.VisualStudioをダウンロード、インストール
　その際、.NETによるモバイル開発を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318297/f511de50-17b3-817a-a063-75130aeb2b99.png)

2.プロジェクト作成で以下を選択
AndroidSDKライセンスには同意を。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318297/fe983ba7-0852-e211-4c3e-a6642a2a2571.png)

え、これだけ？
昔はもっとあれこれ設定してたけど・・・
もうこれだけで本体つないでデバッグしたりも可能。な模様
Mac USキーボードで簡単に「かな」⇄「英数」変換をする方法（command、追加ソフト不要）


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991191/31369453-491f-3fdc-df4f-d364d1cfec1f.png)
Mac の US キーボードはスッキリしたデザインで格好良いですが、不便な点もあります。それは、「かな」と「英数」を切り替える単体キーが無いということです。

JISキーボードならば` スペース` の左右に` 英数` と` かな` をタイプするだけで変換出来ますが、USキーボードだと` ⌘command` +` スペース` で変換する必要があり、手間がかかります。

そこで今回は、あまり使わないキーに「かな」⇄「英数」変換機能を割り当てる方法と、JIS キーボードのように変換できるようにする方法をお伝えします。

#『Caps Lock』キーだけで言語の切り替えをする設定
今回は、普段あまり使わない（というか邪魔な）`caps lock`キーを「かな」⇄「英数」変換キーとして割り当てる方法を記述します。

まず、設定アプリを起動して、「キーボード」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991191/5c539368-abc5-1521-f952-669f16a23058.png)
次に、「入力ソース」タブを選択して、「Caps LockキーでABC入力モードと切り替える」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991191/8fb64e75-e8be-0226-9f59-782bab977c7a.png)
すると、` caps lock` をタイプするだけで「かな」⇄「英数」変換ができるようになりました。ちなみに、` caps lock` キーを長押しするとランプが光り、通常のcaps lock機能を使うことが出来ます。

#『command』キーだけで言語の切り替えをする設定
MacのJISキーボードとUSキーボードの両方を使用している場合、上記の方法だけだと、` スペース` の左右にある` ⌘command`キーを誤ってタイプしてしまいがちです。例えば私の場合だと、MacBook AirのキーボードはJISで、自宅で使う場合は無線のUSキーボードを使用していますが、JISキーボードの` 英数` と` かな`がある位置にUSキーボードでは` ⌘command` があるため、過ってそれをタイプすることがあります。

また、Windows PCとMacの両方を使用している方は、WindowsのControlキーがMacだとcommandキーなので、ときどき間違えることがあるかと思います。

そこで、` ⌘command`キーに言語の切り替え機能を割り当てて、代わりに` (^)Control` キーが` ⌘command` キーとして使えるように変更する方法を記述します。

まず、先程と同様に設定アプリを起動して、「キーボード」を選択します。
次に、「キーボード」タブを選択して「修飾キー...」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991191/449332c2-61c3-0638-f78c-4a363ec9b33f.png)
次に、変更したいキーボードを選びます。
私の場合は無線キーボードのみがUSキーボードなので、ここではUSB Receiverの設定を変更します（MacBookのキーボードがUSキーボードの場合、「Apple内蔵キーボード/トラックパッド」の設定を変更して下さい）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991191/29b332b3-4c89-5d75-ea8a-2ef5972b24cf.png)
次に、以下のように「Control(^)キー」にcommandを割り当て、「Command(⌘)キー」にCaps Lockを割り当ててOKをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991191/17ff438b-fbfd-2889-c715-d26afa508971.png)
すると、まるでJISキーボードと同じように、スペースキーの左右にある` ⌘command`キーをタイプするだけで「かな」⇄「英数」変換ができるようになりました。
代わりに、` (^)Control` キーが` ⌘command` キーとして使えるように変更されました。これでWindows PCのControlキーと同じように使用することが出来るので、WindowsとMacの両方を使い分けている方は、混乱せずに使用することが出来ると思います。

参考になりましたら「LGTM」を押して頂けると嬉しいです！

---
動作確認
macOS Big Sur (version: 11.0.1)
MacBook Air (Apple Silicon M1チップ、2020)
【PHP7技術者認定初級試験】受けてみて

## 背景

### なぜ受けたのか？
・実業務でPHPを書く機会がなかったから
・Webエンジニアとして知っておきたかったから
・資格取得奨励金が出るから

## 受験まで
勉強期間は2週間。平日の朝、夜で2h程度勉強しました。

### 勉強に使ったもの
・公式問題集（PHP7技術者認定[初級]試験問題集）
・[WEB模擬試験](https://study.prime-strategy.co.jp/study/ph7el1/)
・MacBook

参考書は3週。9割正解できるまで復習しました。
WEB模擬試験は、2回受験。参考書より難しい印象を受けました。
MacBookは、PHPのインストールが不要だったのでさっと動作確認したいときに便利でした。

### 受験申し込み
1. Odyssey IDの登録
2. 試験会場の申し込み

受験するには、Odyssey IDを使ってログインする必要があります。
登録は[こちら](https://cbt.odyssey-com.co.jp/cbt/registration/index.action)から

試験会場の申し込みは、個人で行ないます。
試験会場は検索が可能なので、自宅近くで探しました。
（コロナ禍で受けられるスペースが少なく、探すのには苦労しました・・・。）

## 当日
写真付きの身分証明書が必要です。
別試験で運転免許証を筆箱の中に置いてたので忘れそうになりました汗

## 結果
900/1000（結果：合格）となりました。※700以上で合格

試験時間は60分でしたが、40分で解き終わりました。
難易度は、参考書 < 試験 ≦ 模擬試験 くらいに感じました。

## 感想
PHP初心者向けでよく構成されているなと感じました。
理不尽な問題が出題されるわけではなく、きちんと勉強した分取れる問題で良かったです。
Serverless FrameworkとAWS Lambda with Rubyの環境にgemインストール

gemインストールが必要なAWS LambdaのRubyスクリプトをServerless Frameworkでデプロイする方法です。


# 手順概要

プラグインを入れれば簡単にできます。

1. `serverless plugin install -n serverless-ruby-layer`
2. `Gemfile` 作成
3. あとは普通にデプロイすると勝手にいろいろやってくれる


# 手順詳細

## Serverless Frameworkのサービス作成

```console
$ serverless create --template aws-ruby
Serverless: Generating boilerplate...
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v2.16.1
 -------'

Serverless: Successfully generated boilerplate for template: "aws-ruby"
Serverless: NOTE: Please update the "service" property in serverless.yml with your service name
```

ファイルが3つ生成されます。

```
.gitignore
handler.rb
serverless.yml
```


## プラグインインストール

`serverless-ruby-layer` というプラグインをインストールします。

```console
$ serverless plugin install -n serverless-ruby-layer
```

以下のファイルやディレクトリが増えます。

```
node_modules
package.json
package-lock.json
```

Serverless FrameworkがNode.jsで実装されているので、Rubyのプロジェクトなのに `node_modules` や `package.json` が存在することになるようです。


## ソースコード

### serverless.yml

`serverless.yml` は以下の内容にします。 `plugins` のところの記述はプラグインをインストールすると勝手に追記されています。

```yaml
service: sample

frameworkVersion: '2'

provider:
  name: aws
  runtime: ruby2.7
  region: ap-northeast-1

functions:
  hello:
    handler: handler.hello

plugins:
  - serverless-ruby-layer
```


### Gemfile

`Gemfile` を作成し、以下の内容にします。

gemのサンプルとして `holiday_japan` を使ってみます。日本の祝日を判定するgemです。

```ruby
source "https://rubygems.org"

gem 'holiday_japan'
```


### Rubyソースコード

`handler.rb`

```ruby
require 'json'
require 'holiday_japan'

def hello(event:, context:)
  holidayName = HolidayJapan.name(Date.new(2021, 8, 8))
  puts(holidayName) # CloudWatch に "山の日" と書き出される
end
```


## デプロイ

ここまで作成してから `serverless` コマンドでデプロイすると、Lambda本体だけでなく、 `serverless` コマンドが自動でgemインストールしたイメージを作成し、AWS LambdaのLayerとしてアップロードしてくれます。

```
$ serverless deploy -v
```


## 実行

デプロイ結果をAWSマネジメントコンソールで見ると次のように見えます。

Lambda

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/060e8334-b53e-bf9d-cfbc-37722432f802.png)

Layer

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/7d860450-777f-aeb9-1797-65465b9b754a.png)

実行結果のCloudWatch Logs

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/73b0fc65-1707-28c9-4c5a-5053ef1a1af7.png)


# リンク

- (Python版) [Serverless FrameworkとAWS Lambda with Pythonの環境にpipインストール](https://qiita.com/suzuki-navi/items/b5f513f21d37365c248f)
SIEM（シーム）とは

【SIEMとは？】

SIEM：シーム
Security Information and Event Managementの略称。
直訳はセキュリティ情報及びイベント管理となる。

セキュリティ機器やネットワーク機器など（スイッチ、ルーター、ファイアウォール、IPS/IDS、DB等）からログを集めて一元管理し、相関分析によってセキュリティインシデントの予兆や痕跡をを自動的に発見するツール。
標的型攻撃に対する有効的なツールとして注目されている。

■SIEMの機能
①ログの監視
→ログを収集しすぎるとシステムに負荷がかかったり、適切な解析を行えなくなる恐れがあるため、ログの収集/解析範囲を事前に選定しておく必要がある。

②ログの収集と統合
→セキュリティ機器毎に管理画面を開く必要がない。

③ログの相関分析
→不正行為と断定しにくい長期的な攻撃でも、様々な要因から総合的に判断をして脅威かどうかの判定をする。

④インシデントの集中管理
→ログを一元管理していることで大小問わず、インシデント情報を一気に確認できる。

⑤UBA/UEBA機能
UBA/UEBAを搭載したSIEMであれば、誤検知率を減らし正確なセキュリティ対策の実現に役立つ。
※UBA＝User Behavior Analytics
ユーザー行動分析。
脅威と判定されにくいグレーな行為を機械学習によって脅威かどうか判定し、その対応を支援するツール。
内部脅威に対する対策として導入される。
※UEBA＝User and Entity Behavior Analytics
ユーザーの行動だけではなく、情報を扱う設備やソフトウェア（ネットワークに接続されたサーバーや中継器など）を指す「エンティティ」の行動履歴を、機械学習によって自動的に分析する。

■SIEMのメリット
①ログの統合管理ができる。
②相関分析によりセキュリティインシデントを発見できる。
③リアルタイムに分析できるため早期発見につながる。
④分析の手間を大幅に短縮できる。

■SIEMのデメリット
①ネットワークトラフィックが高くなる。
→複数の機器からログを収集するため。

②ログの粒度が粗い。

③ルールの制定など運用開始までに時間がかかる。

④導入コストがかかる。

⑤大量のログ収集によりセキュリティインシデントとは関係のないアラートが上がる可能性もあり、アラートの精査に時間がかかる可能性も。

■SIEMが導入される背景
・コンプライアンス規制の厳格化により、企業がITセキュリティへの投資拡大を迫られている。
SIEMはPCI DSS、GDPR、HIPAA、SOXの各基準への準拠に役立っており、特にGDPRなどは企業の規模に関わらず適用されることから中小企業にも導入の必要性が出てきている。

☆EDRなどと組み合わせて導入するケースも多いようです。
Git初学者のためのメモ


# はじめに
gitは以前から使用していましたが、なんとなく add →　commit → push を使っているだけでした。そこで体系化されたもので学習しようと思い、「GitHub実践入門」でgitの基礎を学んだので、Markdownの練習とgitの自分用のメモとしてこの記事に残しておきます。
今後も追記していく予定です。

>
[GitHub実践入門　~Pull Requestによる開発の変革~](https://www.amazon.co.jp/GitHub%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-Pull-Request%E3%81%AB%E3%82%88%E3%82%8B%E9%96%8B%E7%99%BA%E3%81%AE%E5%A4%89%E9%9D%A9-PRESS-plus/dp/477416366X/ref=asc_df_477416366X/?tag=jpgo-22&linkCode=df0&hvadid=295678107984&hvpos=&hvnetw=g&hvrand=11882595701310408366&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009208&hvtargid=pla-525150537011&psc=1&th=1&psc=1)
>

 ![GitHub実践入門](https://images-na.ssl-images-amazon.com/images/I/51PjpAUHZBL.jpg)


# git概念図
以下の図が私にとっては、一番しっくりくる概念図となっています。

- Working Directory :　全てのファイルはここに属しています。
- Staging index : 変更を加えたファイルを`git add`するとこのエリアになります。
- Local Repository : コミットすると履歴といして管理できます。
- Remote Repository : pushによってローカルリポジトリの内容を反映します。

  
![git概念図](https://www.jrebel.com/sites/rebel/files/blog-images/2016/02/GitHub-cheat-sheet-graphic-v1.jpg)

git add : stage領域へ置き、gitの管理対象下とする
git commit : Localリポジトリへ履歴を残す


# Fork と Pull Requestの関係
>
![Forkのワークフロー](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F284567%2Fc6162ef3-ab22-7062-d9f3-707d999a1a2a.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&w=1400&fit=max&s=b20e60567385a2e68013ac425c39230e)
引用元：[Qiita](https://qiita.com/matsubox/items/09904e4c51e6bc267990)

> 

# HEADとは
HEADがブランチを指すことで自分が現在いるブランチがどれか確認できる仕組みになっています

つまり<br>**コミットの場所を記憶しているのがブランチ、ブランチの場所を記憶しているのがHEAD**
です。ポインタのポインタとなる。

>引用元[Qiita](https://qiita.com/ymzk-jp/items/00ff664da60c37458aaa)
![Qiita](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F102978%2F6a496394-fcc5-035c-288a-d0bf82246f89.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&w=1400&fit=max&s=28827f7ed6779a794e6adef6db3d9b18)
>

# よく使うコマンド

|  コマンド  |  意味  |
| ---- | ---- |
|  git log   |  リポジトリにコミットされたログを確認する  |
|  git diff |  今回のコミットが前回のコミットとどのような差分があるのか確認**(git commit する前にやる癖をつける)** | 
|  git checkout -b <br> git checkout -  | ブランチを作成し、切り替え<br>一つ前のブランチへ切り替え |
|  git merge --no-ff マージするブランチ名 | マージコミットのメッセージを記入する | 
|  git log --graph | ブランチを視覚的に確認 | 
|  git commit -am "commit massege" | git add + git commit | 
|  git commit --amend | 直前のコミットメッセージを修正　 |
|  git reset --hard コミットハッシュ | 指定したハッシュ値のコミットに戻る(歴史を自在に行き来できる) |
|  git reflog | 現在のリポジトリで行われた作業のログを全て確認できる |
|  git remote add origin リポジトリURL | リモートリポジトリを登録  | 
|  git push origin リモートブランチ | リモートリポジトリにローカルに存在するブランチを作成しpush |
【Java】string.formatの使い方

# string.format とは？

引数に指定した書式を元に文字列を整形して返すというメソッドです。

#書き方
第一引数は決められた書式に従って書く必要があります。第二引数以降は第一引数で決めた書式に割り当てるための変数を渡します。

```java
public static String format(String format,Object... args)
```

# 実装例

指定された書式の文字列と引数を使って、書式付き文字列を返します。
**書式は(%〜)と書いて指定**します。
**整数(10進整数)を整形する場合は`d`、文字列を整形する場合は`s`**を使います。

```java
        int year = 2021;
        String str = String.format("今年は%d年です。", year);
        System.out.println(str); //今年は2021年です。

        // はじめに0を追加
		System.out.println(String.format("%05d", 1000)); //01000
		System.out.println(String.format("%06d", 1000)); //001000

		// 文字を追加
		System.out.println(String.format("%dと%d", 1000,2000)); //1000と2000

		// 文字列を整形
		System.out.println(String.format("%s/%s/%s", "2021","01","03")); //2021/01/03

```
Node.jsを勉強する② - テキストファイルの作成方法

##はじめに

前回は、[Node.jsの環境構築](https://qiita.com/arata0520/items/d3afcc76a36f1da83819)についてまとめました。今回はテキストファイルの作成方法を記事にします。
##教材
Udemy
The Complete Node.js Developer Course (3rd Edition)
https://www.udemy.com/course/the-complete-nodejs-developer-course-2/

##Jsファイルの作成とファイルモジュールの導入
まずは、コードを書くファイルを作成します。今回はnodeapp.jsと名付けます。
次に、app.jsの中にrequireを用いファイルを操作するモジュールを導入します。
constを用いて変数fsを定義し、モジュールの中身を代入します。

```javascript:nodeapp.js
const fs = require('fs')
```
##テキストファイルを作成する
次に、"writeFileSync"メソッドを用いて、テキストファイルを作成し、文字も入れます。
カッコの中の一つ目の要素はファイル名、2つ目の要素は、書く文字になります。

```javascript:nodeapp.js
//ファイルモジュールを導入
const fs = require('fs')
//ファイルを作成し、文字を書く
fs.writeFileSync('notes.txt', 'Hello, this is the first message!')
```

実行するにはターミナルにnode ファイル名と入力します。

```terminal:ターミナル
node nodeapp.js
```

##文字を追加する
文字を追加するには、appendFileSyncメソッドを使います。
カッコの中の一つ目が

```javascript:nodeapp.js
//ファイルを作成し、文字を追加する
fs.appendFileSync('notes.txt', 'Hello, this is the first message!')
```

再度実行して、動作を確認しましょう

```terminal:ターミナル
node nodeapp.js
```

テキストファイルを確認して、文字が追加されていれば、完成です。
Node.jsを勉強する① - 開発環境構築

##はじめに
ずっと勉強したいと思っていたNode.js
Udemyの講座で勉強してみました。

備忘録として学んだことを自分なりにまとめて記しておきます。
なお、今回は英語の講座でしたが、英語も勉強できて一石二鳥ですね。

今回は開発環境構築を記事にします。

##教材
Udemy
The Complete Node.js Developer Course (3rd Edition)
https://www.udemy.com/course/the-complete-nodejs-developer-course-2/


##Node.jsのインストール
公式ホームページ（nodejs.org)に行き、最新のNode.jsをダウンロードします
![Node-js.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360425/d8afc971-7f73-cc59-0081-439531989c8b.png)

カスタマイズする必要はないので、インストーラーは"Next"をclickして進め、インストールを完了します。

##ダウンロードされているかチェック
コマンドプロンプトを起動して、node -vでインストールされたバージョンを確認

![node -v.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360425/9a9dac03-7609-46c7-09e2-b65c3ae07f85.png)

##コードのエディタがない場合は、ローカルにインストール
講座では、Visual Studio Code を使用しています。
個人的にatomの方が馴染みがありますが、Visual Studio Codeも使いやすかったです。

ダウンロードはこちらから。(https://code.visualstudio.com)
![Visual-Studio-Code-Code-Editing-Redefined.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360425/8c3ad330-ab35-68a6-3648-0a8ce900970d.png)

##コードを書いてみる
まずは任意のフォルダーをデスクトップにつくり、それをVisual Studio Codeで開きます。
左上にフォルダーが表示されます。
![Screenshot 2021-01-01 143836.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360425/0897e1c0-e16a-2122-ce2d-ab8eff7bb3a9.png)
さらに一番左のNew Fileボタンを押して、nodeapp.jsという名前のファイルを作って下さい。
![Screenshot 2021-01-01 144049.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360425/9faa0ca1-6c70-951e-a69e-ecef9e557950.png)

作ったファイルの中に、console. logを用いてメッセージが表示されるコードを書きます。

```javascript:nodeapp.js
console.log("Hello World!")
```

Terminal >> New Terminalをクリックし、ターミナルを開いて、コードを実行してみます。
![Screenshot 2021-01-01 144654.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360425/0f505316-fcea-eff8-b08c-54f1e2c05e41.png)

```terminal:ターミナル
node nodeapp.js
Hello World!
```
nodeapp.jsでconsole.logの中に設定したメッセージが表示されれば、完成です。
【Symfony】Migrationコマンドまとめ

よく忘れるので自分用にメモしておく。
以下コマンドの前につける`php bin/console`は省略する。

## 1. 事前準備
##### .envファイルを設定する

```./.env
DATABASE_URL="mysql://root:root@db:3306/db_name?serverVersion=13&charset=utf8"
```

##### DB作成
以下のコマンドを使うと .env の接続設定で指定した db_name のデータベースを作成する。

```
$ doctrine:database:create
```

##### collateの文字コードを繋いでるDBに合わせる

```./config/packages/doctrine.yaml
default_table_options:
            collate: utf8_unicode_ci
```


##### Status表示
二つのコマンドが用意されているが、正直どっちを使ってもいいと思う。

```bash
$ doctrine:migrations:status
$ doctrine:migrations:list
```
個人的には`list`の方が簡潔で、かつ`getDescription`メソッドで返している値も表示しれくれるのでよく使っている。

## 2. 生成

##### 方法１
現在のentityとdatabaseの状態を比べて差分のsqlのmigrationsファイルを生成

```bash
doctrine:migrations:diff
```

##### 方法２
空のmigrationsファイルを生成

```bash
doctrine:migrations:generate
```

## 3. 実行

##### 1. 全て実行

```bash
doctrine:migrations:migrate
```

##### 2. ファイル指定して実行
ファイル指定してdownもできる

```bash
doctrine:migrations:excute --up 'DoctrineMigrations\Version20210103062456'
doctrine:migrations:excute --down 'DoctrineMigrations\Version20210103062456'
```


`--dry-run`オプションで実行されるSQL文が確認できるはずだが、なぜか確認されない。。。。
あとで時間ある際に調査、、、、


## 4. Tips

##### マイグレーションを実行せずに履歴情報のみを変更する。

```bash
doctrine:migrations:version {バージョン} (--add|--delete)
```

##### 実行確認を出させないオプション
複数行のコマンドを一気に流す時によくつけるオプション

```
--no-interaction
```

##### 全てのmigrationsファイルの状態を確認

```
doctrine:migrations:status --show-versions
```
*このオプションは最近のバージョンではなくなっているが、`doctrine:migrations:list`コマンドが対応していないバージョンではすごく助けられていた。
EclipseからGitHubにプッシュする【備忘録】

EclipseとGitの連携を5回くらいやっているのですが、
毎回どうやってやるんだっけと調べて、検索上位の記事ではうまくできなくて
手間取るので自分用の備忘録としてまとめます。
Eclipseで作成した新規プロジェクトをGitHubの新規リポジトリにプッシュするまでです。
最初の設定みたいなものは書いていません。
検索上位に出てくる記事で苦労しなかったと思うんですがね。。

## EclipseとGitの連携

### ①チーム→プロジェクトの共有
作成したプロジェクトを右クリックし
![スクリーンショット 2021-01-03 14.59.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649268/36c9e375-fa19-d8bb-3387-2746eb5a5f5a.png)

### ②Gitを選択
![スクリーンショット 2021-01-03 14.59.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649268/7332a78f-3c7c-9c4b-04cb-643ad841aa7d.png)

### ③プロジェクトの親フォルダー内のリポジトリーを使用または作成にチェックする
ここでいつもどうするか迷う
![スクリーンショット 2021-01-03 14.59.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649268/b602d2e7-60b8-adef-34d4-a9d3f3e8dd69.png)

### ④リポジトリーの作成を押す
もう押してしまった後ですが。その後完了ボタン。
![スクリーンショット 2021-01-03 15.08.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649268/0c1f7a3c-fb97-7966-bc4c-a21c77ff1c11.png)

## GitHubにプッシュする
### ①Gitパースペクティブを選ぶ

### ②Gitステージングの＋＋を押してaddする
![スクリーンショット 2021-01-03 15.09.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649268/41e21c3f-553e-b478-0b46-35ea7926c1e4.png)

### ③コミットメッセージを書いてコミットおよびプッシュ
画像なくてすみません。

以上。
BigQueryの日付テーブルにおける、日付指定リファレンス(2020)


#はじめに
BigQueryの日付を付与したワイルドカードテーブルから、日付を指定するクエリをリファレンスとして記載しています。
以前に[「BigQueryの日付テーブルにおける、日付指定リファレンス」](https://qiita.com/Bacchus/items/e3a5250dfeae2e65520d)を投稿しています。日付算術演算子やLAST_DAYファンクションが使えるようになったので、更新しました。

##クエリリファレンス
###前日

```sql
SELECT
  *
FROM
  `ds.table_P*`
WHERE
  _TABLE_SUFFIX = FORMAT_DATE("%Y%m%d", CURRENT_DATE('Asia/Tokyo') - 1)
```

###前月
前月の1日から最終日。
前月１日、前月末日を指定する場合には、BETWEEN〜AND〜が使えます。

```sql
SELECT
  *
FROM
  `ds.table_P*`
WHERE
  _TABLE_SUFFIX BETWEEN 
  FORMAT_DATE("%Y%m%d", DATE_TRUNC(DATE_SUB(CURRENT_DATE('Asia/Tokyo'), INTERVAL 1 MONTH), MONTH))
  AND FORMAT_DATE("%Y%m%d", LAST_DAY(DATE_SUB(CURRENT_DATE('Asia/Tokyo'), INTERVAL 1 MONTH), MONTH))
```

###前年

```sql
SELECT
  *
FROM
  `ds.table_P*`
WHERE
  _TABLE_SUFFIX BETWEEN 
  FORMAT_DATE("%Y%m%d", DATE_TRUNC(DATE_SUB(CURRENT_DATE('Asia/Tokyo'), INTERVAL 1 YEAR), YEAR))
  AND FORMAT_DATE("%Y%m%d", LAST_DAY(DATE_SUB(CURRENT_DATE('Asia/Tokyo'), INTERVAL 1 YEAR), YEAR))
```

###前週
日曜日〜土曜日の指定。

```sql
SELECT
  *
FROM
  `ds.table_P*`
WHERE
  _TABLE_SUFFIX BETWEEN   
  FORMAT_DATE("%Y%m%d", DATE_TRUNC(CURRENT_DATE('Asia/Tokyo') - 7, WEEK(SUNDAY)))
  AND FORMAT_DATE("%Y%m%d", LAST_DAY(CURRENT_DATE('Asia/Tokyo') - 7, WEEK(SUNDAY)))
```

###日付文字列変換など覚え書き

```sql:
SELECT
  FORMAT_TIMESTAMP('%Y-%m-%d %H:%M:%S', CURRENT_TIMESTAMP()), --UTC
  CURRENT_DATETIME('Asia/Tokyo'), --JST
  STRING(CURRENT_TIMESTAMP(), 'Asia/Tokyo'), --日本(+9H)
  STRING(CURRENT_TIMESTAMP(), '+8') --中国など(+8H)
```

##注意点
- CURRENT_TIMESTAMP()を使うと、タイムゾーン指定が出来ないので、DATE型やDATETIME型を使用しています。
- テーブルのプレフィックスには注意が必要です。公式ドキュメントに記載があります。
https://cloud.google.com/bigquery/docs/wildcard-tables#best_practices
例えば、table_20170727とtable_tmp_20170727というテーブルがあった場合、table_*を指定すると両方のテーブルが一致してしまうためです。そのため、パーティションを示す"_P"を付けることにしました。

# 終わりに
前の投稿から３年以上が経っていました。最近はBigQueryと疎遠で、キャッチアップできてないです・・・

#参考
https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#supported-format-elements-for-datetime
日付算術演算子
https://cloud.google.com/bigquery/docs/reference/standard-sql/operators#date_arithmetics_operators
AtomとGithubの連携方法メモ

#はじめに
AtomとGithubの連携方法を調べた時に、役立った資料を作業ログとして残しておく。

#役立った記事
- [GitHub – Atomと連携してPushする方法【ログインと初期設定】](https://howpon.com/6391#AtomGitHub)
pythonでのスライスエラー(´；ω；`)

#エラー発生！！！

pythonにて、無効なメールアドレスをはじくメソッドを書いていました。

```
def isValidEmail(email):
    if email[0] == '@':
        return False
    elif ' ' in email:
        return False
    elif email.count('@') > 1:
        return False
    elif email['@':].count('.') < 1:
        return False
    else:
        return True
```

条件の４個目の「@」以降に「.」が無いメールアドレスをはじく条件を付けたかったのですが、エラーになりました。

エラー内容は「slice indices must be integers or None or have an __ index __ method」
となっておりました。
どうやらスライスの中身は整数である必要があるとのこと。

#解決策
事前に@以降のドメイン名を切り出した変数を用意し、その中で「.」を検索することとしました。成功！

```
def isValidEmail(email):
    domain = email.find('@')
    if email[0] == '@':
        return False
    elif ' ' in email:
        return False
    elif email.count('@') > 1:
        return False
    elif email[domain:].count('.') < 1:
        return False
    else:
        return True
```
根本的な解決ではないかもしれませんが、とりあえず解決！