OmniAICreator/Qiita-1.07M huggingface dataset:
RubyでFirebase Cloud Messagingに利用するアクセストークンを取得する

Rails からネイティブアプリへのプッシュ通知を実装する際に、Firebase Admin SDK を使わずに Firebase Cloud Messaging (FCM) に利用する access_token を取得する方法です。
※ Firebase Admin SDK は Ruby に対応していません

# 利用 Gem
- [googleauth](https://github.com/googleapis/google-auth-library-ruby) - Google Auth Library for Ruby


```ruby:Gemfile
gem 'googleauth'
```

```bash:bash
# インストール
$ bundle
```

# 秘密鍵の取得方法
https://console.firebase.google.com/project/
Firebase のダッシュボードにアクセスし、下記の手順で秘密鍵を取得する。
<img width="1059" alt="firebase_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197676/01b7533e-bb07-2683-9752-15955a5a9e81.png">
**サービス アカウントを作成** をクリックする。
<img width="1059" alt="firebase_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197676/bbf9c46e-2d7e-dcdc-2c89-40ccd618815d.png">
**新しい秘密鍵の生成** をクリックする。
<img width="1059" alt="firebase_3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197676/36f71f06-1c4c-b398-c8e4-51ad0144f577.png">
**キーを生成** をクリックする。

下記のような内容の json ファイルがダウンロードできる。

```json:my-project-name-xxxx-firebase-adminsdk-xxxx.json
{
  "type": "service_account",
  "project_id": "my-project-name-xxxx...",
  "private_key_id": "abcdef012345...",
  "private_key": "-----BEGIN PRIVATE KEY-----xxxxxxx....",
  "client_email": "firebase-adminsdk-xxxx@my-project-name-xxxx.iam.gserviceaccount.com",
  "client_id": "01234567891...",
  ...
  ...
}
```

# アクセストークンの取得方法
ダウンロードした秘密鍵の json ファイルを適切な場所に保存します。
※ ここでは `config/` ディレクトリ配下に `firebase-adminsdk.json` という名前で保存したとする

配置後は、以下のようなコードで取得が可能です。

```ruby
SECRET_KEY_PATH = File.open("#{Rails.root}/config/firebase-adminsdk.json")

def credential
  authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
    json_key_io: SECRET_KEY_PATH,
    scope: 'https://www.googleapis.com/auth/firebase.messaging'
  )
  authorizer.fetch_access_token!
end

# --- 利用側 ---
puts credential['access_token']
# 出力例 : xxxxxxxxxxxxxxxxxxxxxx
```

# 環境変数を使う場合
ダウンロードした秘密鍵の json ファイルをもとに、下記の環境変数を設定する。
- **GOOGLE_CLIENT_ID**
- **GOOGLE_CLIENT_EMAIL**
- **GOOGLE_ACCOUNT_TYPE**
- **GOOGLE_PRIVATE_KEY**

設定後は、下記のようなコードで取得可能になる。

```ruby

def credential
  authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
    scope: 'https://www.googleapis.com/auth/firebase.messaging'
  )
  authorizer.fetch_access_token!
end

# --- 利用側 ---
puts credential['access_token']
# 出力例 : xxxxxxxxxxxxxxxxxxxxxx
```


以上です。
flutter doctor したらSDK Maneger -> Java のバージョンコンボで嵌まったときの対処法

### はじめに

Java8のインストールで困ってる人は下の解決策まで読み飛ばしてください。

### 問題発生の流れ

まず `flutter`を始めるためにインストールします。

インストールしたら`flutter doctor`でちゃんとインストールできたか確認します。

そうするとMacでは大体の人が「SDKのバージョンが古いからあっぷでーとしなさんせ。」と言われます。

```.sh
> flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v1.13.6, on Mac OS X 10.15.2 19C57, locale ja-JP)
[!] Android toolchain - develop for Android devices (Android SDK version 26.0.2)
    ✗ Flutter requires Android SDK 28 and the Android BuildTools 28.0.3
      To update using sdkmanager, run:
        "/Users/ironsand/Library/Android/sdk/tools/bin/sdkmanager" "platforms;android-28" "build-tools;28.0.3"
      or visit https://flutter.dev/setup/#android-setup for detailed instructions.
```

言われるままに以下のコマンドを走らせます。

```.sh
"/Users/ironsand/Library/Android/sdk/tools/bin/sdkmanager" "platforms;android-28" "build-tools;28.0.3"
```

エラーメッセージをメモってなかったんですが、このコマンドを打つと「JDKがありませんよ。」と言われるので、最新(2020/01/30時点で Java SE13)のJavaを入れます。

そしてSDKのアップデートをもう一度実行します。。

```.sh
"/Users/ironsand/Library/Android/sdk/tools/bin/sdkmanager" "platforms;android-28" "build-tools;28.0.3"
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
	at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
	at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
	at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
	at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:73)
	at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:48)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 5 more
```

とちゃんとJavaを入れたのによくわからないエラーが発生します。

それからエラーメッセージでネットを検索するとAndroidSDKはJava8以下じゃないと互換性が無いことを知ることになります。

さらにライセンスの問題で古いバージョンを入れるのは面倒くさい空気になってることを知ることになるでしょう。もうかなり嫌になってくる頃合いですね。

### 解決策

Android Studioに付属してるJavaを使いましょう。

```sh:.zshrc
export JAVA_OPTS=""
export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home"
```

`.bashrc`なり`.zshrc`に上記の環境変数を読ませて`flutter doctor`をしましょう。

### 参考

https://github.com/flutter/flutter/issues/39549
Atcoder ABC099 C - Strange Bank 別解集

AtcoderProblemでは難易度緑後半でなかなか難しいが、解法は色々あるみたい、、、

#再帰
```saiki.py
# coding: utf-8
# Your code here!
N=int(input())

def saiki(tgt,i,count,ans):
    #print(tgt,i,count,ans,temp[i])

    if i==0 or tgt==0:
        ans=min((tgt+count),ans)
        return ans
        
    num=tgt//temp[i]
    while num>=0:
        ans=saiki(tgt-num*temp[i],i-1,count+num,ans)
        if ans<(count+num):
            return ans
        num-=1
    return ans

temp=[1]
n=1
while N>=6**n:
    temp.append(6**n)
    n+=1
    
n=1
while N>=9**n:
    temp.append(9**n)
    n+=1

temp.sort()

print(saiki(N,len(temp)-1,0,10**9))

```
茶色の時に作ったので所々雑ですね
再帰は無限ループ書いちゃったりするのですきじゃない

#動的計画法
```dynamic.py
# coding: utf-8
# Your code here!
N=int(input())

lis=[]

temp=6
while temp<=N:
    lis.append(temp)
    temp*=6

temp=9
while temp<=N:
    lis.append(temp)
    temp*=9

lis.sort(reverse=True)

dp=[10**9]*(N+1)
dp[0]=0

#配列dp[N+1]にインデックスの数字を作るための最小手数をメモっていく
for item in lis:
    for i in range(N+1):
        if dp[i]!=10**9:
            if i+item<=N:
                dp[i+item]=min(dp[i]+1,dp[i+item])
            
ans=10**10
for index,item in enumerate(dp):
    ans=min(ans,item+N-index)
print(ans)

```
こっちの方が簡単・単純でいいとおもった

意識したのはナップザックの解法
後から見てて気づいたが今回みたいにdpにメモるのを1から始めると無限個数ナップザック、逆から始めると1個限定ナップザックになる

#bfs
わからぬ
いつかやる
Codeforces  Educational Codeforces Round 81A (1295A) Display The Number


# 題意
- 998244353  桁表示できるディスプレイがある。各桁は7セグLEDである
- 今、n(最大200,000)のセグメントを光らせることができるとき、最大の数はいくつになるか？述べよ

# 解法
まず、最大桁数を考えると、最大となるセグメントを光らせても、ディスプレイの桁数が足りることはない。

なるべく大きな数を作るには桁を増やすのが最適であるが、これには2セグメントで十分な`1`を用いれる。このため、まず、n//2個の連続した1の数字を作ることができる。

ここで $ n % 2 = 1 $のとき、つまり、1セグメント分余る場合、最大桁数の上のセグメントを光らせて7にすれば最大となる。

※6セグ使って9にするくらいなら111を作った方が桁数が大きくなり、大きな数字になる。

<img width="50%" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/3a1f5d1c-6609-54d8-7520-1bea3f8f332f.png">

# ここにはまった
- `screen which can display up to 998244353 decimal digits`

この998244353`桁`表示できるディスプレイ を 998244353`まで`表示できるディスプレイ と読み間違えた。

```Python
t = int(input())
for _ in range(t):
    n = int(input())
    if n % 2 == 0:
        res = "1" * (n // 2)
    else:
        res = "1" * (n // 2)
        l = list(res)

        l[0] = "7"
        res="".join(l)
    print(res)
```
https://codeforces.com/contest/1295/submission/69742919
macOSバージョンアップしたらgitが使えなくなった時にしたこと

バージョン10.15.2から10.15.3にアップデートしたあと、git initしたら以下のエラー発生

    xcrun: error: invalid active developer path (/Applications/Xcode.app/Contents/Developer), missing xcrun at: /Applications/Xcode.app/Contents/Developer/usr/bin/xcrun



__対処__
---
ググってみた結果、以下のコマンドで解決できるようなので実行

    $ xcode-select --install



すると今度は以下のエラー発生

    xcode-select: error: command line tools are already installed, use "Software Update" to install updates

すでにインストールされているからアップデートしろ・・・？？？
最新のバージョンではないということ？

__更新の確認__
---
更新が来ているソフトウェアがあるか確認

    $ softwareupdate --list
↓結果

    Software Update Tool

    Finding available software
    No new software available.

アップデートできるソフトウェアが無い・・・
混乱してきた・・・


もう一度ググってみた結果、以下のコマンドで対処できるようなので実行

    $ sudo xcode-select -switch /Library/Developer/CommandLineTools

参考にさせて頂いた記事
https://qiita.com/kuriya/items/69d1e510fcaec4afd8c9

パスワードを入力し、git --versionでgitの生存確認

    $ git --version
    git version 2.21.0 (Apple Git-122.2)

認識してくれた
解決！！！
SQLの基本構文（PostgreSQL）

# CREATE TABLE（テーブル作成）

CREATE TABLE テーブル名 (列名 データ型 制約 [, 列名 データ型 制約 …] );

```sql
CREATE TABLE city (id serial PRIMARY KEY, name varchar(3));
```

# INSERT（作成）

INSERT INTO テーブル名(カラム名1,カラム名2,・・・) VALUES (値1,値2,・・・)
カラム名のところは省略可能で、その場合は値を間違えずに１番目のカラムから順番に書く。

```sql
INSERT INTO city (name) VALUES ('北海道');
```

# UPDATE（更新）


# SELECT（参照）

```sql
# SELECT * FROM city;
 id |  name  
----+--------
  1 | 北海道
(1 row)
```

# ユーザ作成

一般ユーザをパスワードとあわせて作成する

```
CREATE ROLE citymanager LOGIN PASSWORD 'pass';
```

# データベースのオーナ変更

ALTER DATABASE データベース名 OWNER TO 変更後のオーナ;
データベースのオーナーを変更しても、そのデータベース内のテーブルのオーナが変更になるわけではない。別途変更する必要がある。

```
ALTER DATABASE testdb OWNER TO citymanager;
```

# テーブルのオーナ変更

ALTER TABLE テーブル名 OWNER TO 変更後のオーナ;

全テーブル（＋シーケンス等も）変更するのは大変なので、こちらの方の方法が簡単。ただし、postgresユーザから変更をかける場合、管理系のテーブル（pg_なにがし）もリストアップされるので、それらはやらず、publicテーブルに絞る。
[PostgreSQLでテーブルオーナを一括変更する方法](https://qiita.com/windows222/items/49d413f6558ade79809a)
PostgreSQL運用

# ダンプ&リストア（平文形式）

平文（SQL形式）で取得する。このとき、リストア時のためにテーブル削除やテーブル作成構文を含めるかどうかオプション指定できる。
リストアはpsqlコマンドで行う。

※INSERT文形式とCOPY文形式のどちらかを選択できます。INSERT形式の場合、「改行」を含むデータをこの平文形式で取得すると、リストアするときに改行が反映されなくなることがあったと思います（ちょっとうろ覚えなので違ったらすみません）。そのときは手動でCHR(10)をデータ中に追加して元に戻しましたが。

```
$ pg_dump testdb > /tmp/testdb.dump
```

# ダンプ&リストア（アーカイブ形式）

## ダンプ

アーカイブ形式（圧縮されてます）で取得する。リストア時のためのテーブル削除とかのオプションは不要（リストア時に指定する）。

```
$ pg_dump -F c testdb > /tmp/testdb.dump
```

平文とアーカイブの使い分けですが、開発中のように、SQL文を手動で書き換えたりするのなら平文の方がよいです。ただし上記のように改行は要注意だったと思います。運用中など、単純にバックアップ・リストアができればいいなら、アーカイブ形式の方が高速・容量も小さくて良いと思います。

## リストア

-cでリストア前にデータを削除する

```
$ pg_restore -c -d testdb /tmp/testdb.dump
```

# レプリケーション

こちらの方のページが詳しいです
[PostgreSQL9.6 レプリケーション設定](https://qiita.com/nyao/items/50c8216050b726838e45)

※以下、断片的なメモです（そのうち整理します）
recovery.confに、restore_commandを設定することで、たしかレプリケーションが追い付かなくなったときのコマンドを指定できる。SCP時（SSH接続）に鍵指定が必要な場合は「-i 鍵ファイル名」をオプション指定すればよい。

``` :recovery.conf
restore_command = 'scp マスタのホスト名orIPアドレス:/path/to/archive_log/%f %p'
```
SPAについて無知だったので少し調べた



SPAという言葉は聞いたことがあったが、無知だったので少し調べてまとめた。

## SPAとは
SPAとはSingle Page Applicationの略であり、単一のWebページでアプリケーションを構成する設計構造の名称や考え方である。

SPAを利用したWebアプリケーションは、**ページ全体をレンダリングするのではなく**、**変更する部分だけ書き換える**。これによって、サーバーのリソース、そしてサーバー～クライアント間の通信量を削減することができ、快適なユーザーエクスペリエンスを提供することができる。

実際の流れとしては以下のようなイメージ

1. ユーザーがアクションを起こす
2. そのアクションに必要なデータだけをサーバーに要求
3. 返ってきたデータをJavaScriptで処理
4. 差分を描写

「雰囲気は理解できた。」

## SPAのメリットとデメリット

次にSPAのメリットとデメリットについて。

### メリット
#### 動作性の向上
ページ全体をレンダリングするのではなく、ブラウザ側でできる処理はJavaScriptで終わらせることで、サーバとの通信量を最低限に抑えることができる。

「確かに納得できる。」

#### より高度なWeb表現
SPAはユーザーのアクションに対して必要な部分のみを更新することで、ブラウザの挙動に縛られることがなく、幅の広いUIを実装することができる。
また、オフラインでのページ閲覧、プッシュ通知など、ネイティブアプリで主に使われるような機能を実装することもできる。

「ブラウザによって挙動が変わるという部分が経験不足でいまいちピンとこない部分。」

### デメリット
#### 読み込みに時間がかかる
JavaScriptのコード量が増加することから、初回の読み込みの際に時間がかかる。そのため、直帰率の高いサービスでは、アクセス時に時間かかることから向いていないとされる。

「これは納得できる。シンプルなHTMLだけを読み込むことに比べると、データ量はかなり多そう」

## SPAで使われる技術
* JavaScriptフレームワーク、ライブラリ（Angular、Vue.js、Reactなど）
* CSS Preprocessor（sass、stylusなど）
* 通信技術（Ajax,WebSocketなど）
* バックエンド技術（Ruby on Railsなど）
* HTML5/CSS3

「決して特別なものはなく、既存の技術をうまく組み合わせて実現されたようなイメージ。JSのフレームワークについては完全に未知(響きは聞いたことあった)」

### 主なJSのライブラリ
#### React
Facebook製のViewライブラリ

#### Vue.js
オープンソースなフレームワーク

#### Angular
Google製のフレームワーク

## まとめ
雰囲気は理解できた。サーバーからHTML返すのではなくて、フロントからAPIを叩いて、必要な部分のみを変えていこう的なイメージ。
勉強記録　19日目 〜コンパイラによるコピーコンストラクタの自動生成の禁止〜 - Effective C++ 第3版 -

#　はじめに

Effective C++ 第3版の6項31ページから勉強していきます。
今回は、「コンパイラによるコピーコンストラクタの自動生成の禁止」についです。

# Effective C++ 第3版 - 6項　コンパイラが自動生成することを望まない関数は使用を禁止しよう -

## コンパイラによるコピーコンストラクタの自動生成の禁止

### コンパイラによるコピーコンストラクタの自動生成の禁止

[前回の投稿](https://qiita.com/eierapfel/items/95635a86d3dee967a8d8)で、クラス内で、コピーコンストラクタ、コピー代入演算子、デストラクタを宣言しなければ、コンパイラが自動でそれらを生成すると書きました。

しかし、コピーコンストラクタ、コピー代入演算子を使用することが望ましくない場合でも、自動で生成してしまいます。
以下に例を示します。
例のように、HomeForSaleオブジェクトをコピーするようなコードがあれば、コンパイルできないようにしたいと思います。

```cpp
class HomeForSale {
 public:
  explicit HomeForSale(const std::string &city, const int &value) {
    city_  = city;
    value_ = value;
  }

 private:
  std::string city_;
  int         value_;
};

HomeForSale h1("Tokyo", 2);
HomeForSale h2("Osaka", 3);
HomeForSale h3(h1);  // h1をコピーコンストラクタでコピーしようとしている
                     // これをコンパイルできないようにしたい
h1 = h2;             // h2を代入によってコピーしようとしている
                     // これをコンパイルできないようにしたい

```

しかし、このコードをコンパイルを禁止する簡単な方法はありません。
普通に、クラスに特定の関数を使用したくない場合、その関数を宣言しなければ良い。
しかし、コピーコンストラクタ・コピー代入演算子は、上で言ったように、コンパイラが自動で生成してしまいます。
一方、コピーコンストラクタ・コピー代入演算子を宣言してしまうと、やはりコピーをサポートすることになってしまいます。

この問題は、「コンパイラが生成する関数は、すべてpublic」というのが原因です。
コピーコンストラクタ・コピー代入演算子の自動生成を避けるためには、プログラマ自身が宣言するしかないのです。
ただし、publicではなく、privateに宣言します。

これらの関数を明示的に宣言することで、コンパイラによる自動生成を防ぐことができる。
さらに、それらがprivateに宣言されているのであれば、それらを外部から利用することはできなくなります。

しかし、他のメンバ関数はprivateな関数を呼び出すことできるので、
コピーコンストラクタ・コピー代入演算子の宣言だけし、定義を書かないことで、メンバ関数からの呼び出しを防ぐ。

そのため、下のようになります。

```cpp
class HomeForSale {
 public:
  explicit HomeForSale(const std::string &city, const int &value) {
    city_  = city;
    value_ = value;
  }

 private:
  std::string city_;
  int         value_;

  HomeForSale(const HomeForSale&);              // 追加
  HomeForSale &operator=(const HomeForSale &);　// 追加
};

HomeForSale h1("Tokyo", 2);
HomeForSale h2("Osaka", 3);
HomeForSale h3(h1);  // コンパイルエラー
h1 = h2;             // コンパイルエラー
```

以下に、勉強で使用したコードを示します。

### サンプルコード

```cpp
#include <iostream>

/*
  Effective C++ 6項
  コンパイラが自動生成するコピーコンストラクタを生成しないようにする方法

*/

class HomeForSale {
 public:
  explicit HomeForSale(const std::string &city, const int &value) {
    city_  = city;
    value_ = value;
  }

 private:
  std::string city_;
  int         value_;

  HomeForSale(const HomeForSale&);
  HomeForSale &operator=(const HomeForSale &);
};

int main(int argc, char *argv[]) {
  std::cout << "6_no_copy_constract.cpp" << std::endl;
  HomeForSale h1("Tokyo", 2);
  HomeForSale h2("Osaka", 3);
  HomeForSale h3(h1);  // h1をコピーコンストラクタでコピーしようとしている
                       // これをコンパイルできないようにしたい
  h1 = h2;             // h2を代入によってコピーしようとしている
                       // これをコンパイルできないようにしたい

}
```

### 実行結果


## 参考文献

[1] https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0
#twitch　のフォローとフォロワの相互関係を確認するツール

githubと改行ルールが違って二重管理になるため、ここにはgithubのREADME.mdのコピペを載せます。
(githubにあっても検索で探せないため。)
https://github.com/github895439/twitch_ff_check

```plaintext:README.md
本内容を利用した場合の一切の責任を私は負いません。

環境
OS
OS 名: Microsoft Windows 10 Home
OS バージョン: 10.0.18362 N/A ビルド 18362
システムの種類: x64-based PC

node.js
node-v10.16.0-win-x64
request@2.88.0

手順
twitchにアプリ登録
APIを使用するアプリ(≠拡張機能)を登録する。
(要2段階認証。
登録後、再度登録したアプリを「管理」で開き、クライアントIDが表示されていないなら「新しい秘密」で発行する。)
https://dev.twitch.tv/console/apps

自分のID確認
下記のコマンドを実行して自分のID(≠ログインID)を確認する。
コマンド出力のid属性の値が自分のIDである。
curl -H "Client-ID: <クライアントID>" -X GET "https://api.twitch.tv/helix/users?login=<ログインID>"

node.jsにrequestモジュールをインストール
npm install request

本ツールをダウンロード
https://github.com/github895439/twitch_ff_check

ダウンロードしたものを展開

ツールの設定
ff_check.js内の下記を設定する。

const CLIENT_ID = "<クライアントID>";
const SELF_ID = "<自分のID>";
ツールを実行(※markdownがおかしく本来は手順7)
>node ff_check.js
https://api.twitch.tv/helix/users/follows?from_id=略&first=100
https://api.twitch.tv/helix/users/follows?to_id=略&first=100
following: 略
follower: 略

# both
略

# onlyToSelf
略

# onlyFromSelf
略

>
備考
大したことではないけど。
前はフォローもフォロワも誰もが見えてたけど、今はフォローは本人しか見えない。
けど、APIからだと他人のフォローも見える。
クリエイターダッシュボードと今までの画面とでUIが統一されてないから過渡だったりするせいかも。
か、後から修正されたり。
1アクセスでの最大取得は100で、私は100もいないのでツールは対応していない。
対応する場合は、レスポンスのpaginationを次のクエリーにafterで指定すればできると思う。

参考
twitch API
https://dev.twitch.tv/docs/api/reference

requestモジュール
https://github.com/request/request

履歴
2021/03/11　100以上のフォロワーに対応
　仕組み上は上限はないが、レートリミットに対応していないため、強制的に約200くらいまでにしている。
　レートリミットに対応すれば簡単に強制止めを外せると思う。
　フォロワーで配信履歴のあるユーザーを把握したかったので、「# User who has archive in onlyToSelf」下に該当するユーザーのURLを表示するようにした。
2020/05/23　5月頭のAPI変更に対応
　requestパッケージがdeprecateになったため、axiosパッケージを使うようにも変更した。
　このため、axiosパッケージを別途インストールする必要がある。
　クライアントシークレットも必要になったため、設定を別ファイル(data/setting.json)に分離した。
2020/05/18　5月頭にAPIの変更があり、それによって認証エラーになるようになったもよう。変更に対応させるつもり。
```

# 主な履歴
2023/09/18
APIのURLが変わったっぽい上に権限が上がったらしく、このシーケンスでは認証が足りず機能しなくなった。
対応はしない。
#Ruby のあれなんだっけ？ 配列からCSVの文字列やインスタンスを生成する、元に戻す

```rb
require 'csv'

csv_strings = CSV.generate { |csv| csv << ['A', 'B']; csv << ['C', 'D'] }
# => "A,B\nC,D\n"

CSV.new(csv_strings)
# => <#CSV io_type:StringIO encoding:ASCII-8BIT lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">

CSV.new(csv_strings).read
# => [["A", "B"], ["C", "D"]]
```

# Ref

Class: CSV (Ruby 2.6.1)
https://ruby-doc.org/stdlib-2.6.1/libdoc/csv/rdoc/CSV.html

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2971








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Rubyで使える！競技プログラミング、小手先TLE対策

AtCoderでRubyを使って競技プログラミングをしている物好きな人はいますかね。私もです
Rubyで競技プログラミングをしていると、TLEとの戦いになることがあります。
そんなとき、オーダーレベルでのアルゴリズムの改良ができれば最高ですが、そんなひらめきがいつでも降ってくるわけがない。
というわけで今回は小手先のテクニックによって少しでも実行時間を短くする方法を紹介します。

## バージョン情報

* Ruby 2.3.3

## 文字列から文字の比較はしない！

```rb
str = 'abc'
str[0]
# => "a"
```

ベンチマークは後で乗せますが、この`str[0]`はめっちゃ遅いです・・。おそらく添え字アクセス時に、Stringの新しいインスタンスを作成しているせいでしょう。
なので、`.chars`メソッドで1文字毎の配列にしてしまいます。

```rb
str = 'abc'.chars
# => ["a", "b", "c"]
str[0]
# => "a"
```

このアクセスであれば、添え字アクセス時に新しいStringのインスタンスは作られないので、ループを回す場合は結構早くなります。

さらに、文字列の比較よりは数値の比較のほうが早いですよね。なので、`.codepoints`メソッドで数値として持ってしまうのが良いです。

```rb
codepoints = 'abc'.codepoints
# => [97, 98, 99]
str[0]
# => 97
```

では上記3パターンのベンチマークを取ってみます。

```rb
require 'benchmark'

str = 'abc' * 100
N = 10000000
A = 'a'

Benchmark.bmbm do |x|
  x.report 'str' do
    N.times do
      str[0] == A
    end
  end

  x.report 'chars' do
    chars = str.chars
    N.times do
      chars[0] == A
    end
  end

  x.report 'codepoints' do
    codepoints = str.codepoints
    N.times do
      codepoints[0] == 97
    end
  end
end
```

結果はこう。

```
Rehearsal ----------------------------------------------
str          1.290000   0.000000   1.290000 (  1.299665)
chars        0.500000   0.000000   0.500000 (  0.498776)
codepoints   0.400000   0.000000   0.400000 (  0.402605)
------------------------------------- total: 2.190000sec

                 user     system      total        real
str          1.280000   0.000000   1.280000 (  1.281719)
chars        0.490000   0.000000   0.490000 (  0.498172)
codepoints   0.390000   0.000000   0.390000 (  0.394821)
```

codepoints早いですね。
なので、大量のループがあり、その中で文字列中の1文字を比較するような時は、文字列で持たずにcodepointsで持っておくとTLEを回避できることがあるかもしれません。

## ネストの深い配列を避ける！

こんな二次元配列があるとして、

```rb
DATA = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
```

こんな風にアクセスするのが普通かもしれません。

```rb
3.times do |i|
  3.times do |j|
    DATA[i][j]
  end
end
```

が、ループの中においては、これより若干早くなる可能性がある書き方が存在します！
それが、これ。

```rb
3.times do |i|
  data = DATA[i]
  3.times do |j|
    data[j]
  end
end
```

ほんとに！？
って思うかもしれませんが、ベンチマーク取ってみます。

```rb
require 'benchmark'

N = 5000

DATA = N.times.map { N.times.map { rand(100) } }

Benchmark.bmbm do |x|
  x.report 'direct' do
    N.times do |i|
      N.times do |j|
        DATA[i][j]
      end
    end
  end

  x.report 'tmp' do
    N.times do |i|
      data = DATA[i]
      N.times do |j|
        data[j]
      end
    end
  end
end
```

```
Rehearsal ------------------------------------------
direct   1.000000   0.000000   1.000000 (  0.999422)
tmp      0.870000   0.000000   0.870000 (  0.875144)
--------------------------------- total: 1.870000sec

             user     system      total        real
direct   1.040000   0.000000   1.040000 (  1.055139)
tmp      0.870000   0.010000   0.880000 (  0.872905)
```

若干早いですね。
この若干によりTLEを回避できるかもしれません！

## 終わりに

`map`より`map!`を使うだとか、巷でよく言われている小手先のテクニックについてではなく、あまり見ない2つの手法を紹介しました。

早い言語を使っている皆さんは、なんでこんな苦労をしてまでRubyで競技すんの？Mなの？
と思われるかもしれませんが、まぁ、これはこれで楽しんでるんで気にしないでください！
Leetcode: Path Sum

```ruby
require 'test/unit'
require 'pry'
class PathSum < Test::Unit::TestCase

  def test_has_path_sum

    #[1, 2, 2, 3, 4, 4, 3]

    tree = TreeNode.new(5)
    tree.left = TreeNode.new(4)
    tree.left.left = TreeNode.new(11)
    tree.left.left.left = TreeNode.new(7)
    tree.left.left.right = TreeNode.new(2)
    tree.right = TreeNode.new(8)
    tree.right.left = TreeNode.new(13)
    tree.right.right = TreeNode.new(4)
    tree.right.right.right = TreeNode.new(1)

    assert(has_path_sum(tree, 22))
    assert(!has_path_sum(tree, 25123123))
  end

  def has_path_sum(node, sum)
    return false if node.nil?

    # Checking if node is a root node
    if node.left.nil? && node.right.nil?
      # If root's value is sum, we got the answer!
      if node.val == sum
        return true
      else
        return false
      end
    end

    if has_path_sum(node.left, sum - node.val)
      return true
    end

    if has_path_sum(node.right, sum - node.val)
      return true
    end

    false
  end

end


# Definition for a binary tree node.
class TreeNode
  attr_accessor :val, :left, :right

  def initialize(val)
    @val = val
    @left, @right = nil, nil
  end
end
Leetcode: Is Symmetric 

```ruby

require 'test/unit'
require 'pry'
class IsSymmetric < Test::Unit::TestCase

  def test_is_symmetric

    [1, 2, 2, 3, 4, 4, 3]

    tree = TreeNode.new(1)
    tree.left = TreeNode.new(2)
    tree.left.left = TreeNode.new(3)
    tree.left.right = TreeNode.new(4)
    tree.right = TreeNode.new(2)
    tree.right.left = TreeNode.new(4)
    tree.right.right = TreeNode.new(3)

    [1, 2, 2, nil, 3, nil, 3]
    tree = TreeNode.new(1)
    tree.left = TreeNode.new(2)
    tree.left.right = TreeNode.new(3)
    tree.right = TreeNode.new(2)
    tree.right.right = TreeNode.new(3)

    assert(!is_symmetric(tree))
  end

  def is_symmetric(tree)
    tree.nil? || check(tree.left, tree.right)
  end

  def check(left_subtree, right_subtree)
    if left_subtree.nil? && right_subtree.nil?
      true
    elsif left_subtree && right_subtree
      left_subtree.val == right_subtree.val &&
          check(left_subtree.left, right_subtree.right) &&
          check(left_subtree.right, right_subtree.left)
    else
      false
    end
  end

end


# Definition for a binary tree node.
class TreeNode
  attr_accessor :val, :left, :right

  def initialize(val)
    @val = val
    @left, @right = nil, nil
  end
end
カプセル化

#カプセル化とは
カプセル化をする理由としては、共同開発で他の人にプロパティやメソッドを触らせないようにするためにある。バグの防止になる。

#カプセル化をしたプロパティやメソッドへのアクセス方法
クラス外からはアクセスできない。クラス内からでのみアクセスできる。

#カプセル化のメリット
内部の構造を知らなくてもそれを利用することができる。例えば、スマホの内部構造は知らないがボタンをタップするだけでLINEや電話、ゲームができる。

#カプセル化のデメリット
内部に問題が生じた場合はそれに対応することができない。例えば、スマホが故障してLINEや電話、ゲームができなくなったとしても中身の構造がわからないのでどうすることもできない。
Docker+DjangoでPostgreSQLを使う

#はじめに
Docker+DjangoにPostgreSQLをセッティングしテストデータを登録します。
OSはmacを使用します。

データベース用のコンテナをアプリケーション本体とは別に起動しdocker-composeで制御します。

本記事は[DjangoアプリをDocker上に構築しAWS Fargateにデプロイする](https://qiita.com/keita_gawahara/items/66e58a6eed5c0c5f31d2)プロジェクトの一部です。

#PostgreSQLについて
DjnagoにはデフォルトのデータベースとしてSQLiteが選択されています。しかし、アプリケーションのスケールアウトを考えるとSQLiteではスペック面で物足りません。そこで、スケールアウトに対応できるデータベースであるPostgreSQLを使用します。

PostgreSQLのソースは全て公開されており、用途を問わず無料で利用できます。他の商用／オープンソースのRDBMS製品と比較してもまったく遜色のない、高い性能、機能性、そして信頼性を誇るRDBMSです。
またAWS RDSでもPostgreSQLはサポートされており開発環境からプロダクトション環境まで一貫して使用することが可能です。

#準備
Docker上にDjangoを起動させます。詳細手順については下記リンクを参照ください。
下記リンクで作成したプロジェクトを基に進めて行きます。

[docker-compose upを用いてDockerコンテナ上でDjangoを起動する](https://qiita.com/keita_gawahara/items/c0f525190b39395d4170)

#管理者権限のあるユーザの作成

create super userコマンドで管理者権限のあるユーザーを作成します。

まずはコンテナを起動します。同じウインドウでコマンドが打てるようデーモン起動します。
デーモン起動の際は-dのオプションコマンンドを使用します。

```
$ docker-compose up -d
```

Docker上でコマンドを使用する際はdocker-compose exec webを頭につけます。
webはコンテナ名に置き換えてください。

その後、実行したいコマンドを続けて入力します。python manage.py createsuperuserで管理者権限のあるアカウントを作成できます。
実行するとメールアドレスとパスワードを聞かれるので入力してください。

```
$ docker-compose exec web python manage.py createsuperuser
```

その後、コンテナを停止しておきます。

```
$ docker-compose down
```

#docker-compose.ymlへのPostgreSQLの追加
docker-compose.ymlにデータベース関連の記述を追加します。


```docker-compose.yml
version: '3.7'

services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    ports:
      - 8000:8000
    depends_on:        #追加
      - db             #追加
  db:                  #追加
    image: postgres:11 #追加

```

ビルドします。するとdb用のコンテナが立ち上がることが確認できます。

```
$ docker-compose up -d --build

...
Creating hello_db_1 ... done #DB
Creating hello_web_1 ... done
```

#Djangoの設定

デフォルトではsqlite3が設定されています。これをpostgreSQL用に更新します。

```hello_project/settings.py
#削除
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

#追加
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': 'db',
        'PORT': 5432
    }
}
```

#Pyscopgのインストール

settings.pyの設定を変更しただけでは動かせません。
postgreSQLとDjangoを繋ぐライブラリであるPyscopgのインストールが必要です。

pipenvを用いてインストールします。

```
$ docker-compose exec web pipenv install psycopg2-binary==2.8.3
```

ライブラリをインストールしたので、一度コンテナを停止しビルドします。
その後、 http://127.0.0.1:8000/ へアクセスしwelcomeページが表示されれば設定は完了です。

```
$ docker-compose down
$ docker-compose up -d --build
```


#データベースへの接続確認

データベースに変更を加えた際は、migrateコマンドでその都度データベースのマイグレーションが必要になります。マイグレーションしていない状態でデータベースに接続するとProgrammingErrorが起きます。開発をしているとよく出会うエラーですProgrammingErrorの際はデータベース周りをまず疑うのが良いと思います。

```
$ docker-compose exec web python manage.py migrate
$ docker-compose exec web python manage.py createsuperuser
```

その後、http://127.0.0.1:8000/admin へアクセスし管理者の名前とパスワードを入力すると管理者ページに入ることができます。
管理者ページでaddボタンを押すと、データベースにGUIからデータの追加等ができます。

#さいごに
Djangoの管理者ページはテストデータの追加時など非常に使い勝手がよいです。
これでDocker+Djangoの環境でPostgreSQLのセッティングができました。
【JavaScript】Cookie , localStorage, sessionStorageの違い

## はじめに
ブラウザで保存出来る情報、以下３点の**違い**について簡単にまとめました。

- Cookie
- localStorage
- sessionStorage

## 環境
```yaml
OS: macOS Catalina 10.15.3
Chrome: 78.0.3904.108（Official Build） （64 ビット）
```
## 結論：比較表

||Cookie|localStorage|sessionStorage|
|:-:|:-:|:-:|:-:|
|保存容量|**4KB**|10MB|5MB|
|対応ブラウザ|**HTML4**/HTML5|HTML5|HTML5|
|ブラウザのどこで有効か|どこでも|どこでも|**同じタブ内**|
|有効期限|任意設定|**基本は消えない**|**タブを閉じたとき**|
|保存される場所|**ブラウザとサーバー**|ブラウザのみ|ブラウザのみ|
|HTTPリクエストで送信|**される**|されない|されない|

### 特記事項
- Cookieの容量は**4KBと小さい**
  HTTPリクエストで**ヘッダ**としてブラウザからサーバーに送信されるため、容量が大きいとパフォーマンスに影響が出てしまう

- CookieであればHTML4でも対応出来る。つまり、**古いブラウザ**にも対応出来る
- localStorageとsessionStorageは**保存期間**が長い方がいいか、短い方がいいかで使い分ける


## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:

## 参考にさせて頂いたサイト（いつもありがとうございます）
- [JavaScript Cookies vs Local Storage vs Session - YouTube](https://www.youtube.com/watch?v=GihQAC1I39Q)
- [HTTP Cookie - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies)
Pythonでネストしたdictをマージしたい

ネストしたdictをマージしたかったのだけど、適切な記事が全く見当たらない。

とりあえずdictをつくる。

```python
dict1 = {
	"depth1_a": "x1a",
	"depth1_b": "x1b",
	"depth2_1": {
		"depth2_a" : "x2a",
		"depth2_b" : "x2b"
	},
	"depth3_1": {
		"depth3_2": {
			"depth3_3_a" : "x33a",
			"depth3_3_b" : "x33b"
		}
	}
}

dict2 = {
	"depth1_a": "y1a",
	"depth1_c": "y1c",
	"depth2_1": {
		"depth2_a" : "y2a",
		"depth2_c" : "y2c"
	},
	"depth3_1": {
		"depth3_2": {
			"depth3_3_a" : "y33a",
			"depth3_3_c" : "y33c"
		}
	}
}
```

結果として欲しいのは、"depthx_a"はdict2の値で上書きされる、"depthx_b"と"depthx_c"は両方とも残る、というものです。

[複数の辞書のマージ方法いろいろ](https://qiita.com/kk6/items/6362a5fc9f3f06a5969a)などを参考に幾つか試してみたのですが、ネストの二段階目以降で"depthx_b"が消えます。

```python
dict1.update(dict2)
print(dict1)

{
	"depth1_a": "y1a",
	"depth1_b": "x1b",
	"depth2_1": {
		"depth2_a": "y2a",
		"depth2_c": "y2c"
	},
	"depth3_1": {
		"depth3_2": {
			"depth3_3_a": "y33a",
			"depth3_3_c": "y33c"
		}
	},
	"depth1_c": "y1c"
}
```

ネストの一段階目にあるdepth1_a/depth1_b/depth1_cは想定通りになりましたが、それ以外は中身を見に行かずにキーで上書きされてしまいました。

Python3.3からは[ChainMap](https://qiita.com/Kodaira_/items/b2cd37dfe216746723cc)というのがあるらしいので試してみます。

```python
from collections import ChainMap
dict_map = ChainMap(dict1, dict2)
dict(dict_map)

{
	"depth1_a": "y1a",
	"depth1_c": "y1c",
	"depth2_1": {
		"depth2_a": "y2a",
		"depth2_c": "y2c"
	},
	"depth3_1": {
		"depth3_2": {
			"depth3_3_a": "y33a",
			"depth3_3_c": "y33c"
		}
	},
	"depth1_b": "x1b"
}
```

はいだめー。

結局最終的に[自力でやるしかない](https://techblog.recochoku.jp/5748)のかよ、めんどくさいなあ、などと彷徨ってたら[dictknife.deepmerge](https://pypi.org/project/dictknife/0.4.0/)とかいうのを見つけました。
名前からして期待しかない。

```python
from dictknife import deepmerge
deepmerge(dict1, dict2)

{
	"depth1_a": "y1a",
	"depth1_b": "x1b",
	"depth2_1": {
		"depth2_a": "y2a",
		"depth2_b": "x2b",
		"depth2_c": "y2c"
	},
	"depth3_1": {
		"depth3_2": {
			"depth3_3_a": "y33a",
			"depth3_3_b": "x33b",
			"depth3_3_c": "y33c"
		}
	},
	"depth1_c": "y1c"
}
```

これだよ俺の求めていたものは！

ただ残念ながら異なる型を突っ込んだ時の挙動が微妙です。
`"depth3_3_a": None`みたいにリテラル値にNoneを突っ込んだら上書きされてNoneになるのですが、ネストの枝そのものを削除したくて`"depth3_2": None`としたら単に無視されました。
それならばと`"depth3_2": ""`にしたらエラーになりました。
残念。

しかしこのdeepmerge、日本語情報が全くさっぱりびっくりするほど出てこないな。
便利なのでみんなも使うといいと思います。
mailtrapの使い方

開発環境でメールの動作確認をする際に[mailtrap](https://mailtrap.io/)を使用しているのですが、設定に迷うことがあったので、備忘録としてまとめていきます。

# 前提
mailtrapへのサインアップが済んでいる

# 設定
InboxesのDemo inboxが作成されています。これの歯車をクリックすると設定する項目を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88791/1a528abc-6459-4b2b-f7d9-c4a721383d8d.png)

ページへ遷移するとcredentialとサンプルコードがあるので、自身の環境にあったコードがあれば、そのままコピペしたら動作します。
自分の場合は、fuelphpだったので、それを選択して、貼り付けました。
```
return array(
  'driver' => 'smtp',
  'smtp' => array(
    'host' => 'smtp.mailtrap.io',
    'port' => 2525,
    'username' => 'xxxxxxxxxxxxxx',
    'password' => 'xxxxxxxxxxxxxx',
    'timeout' => 5
  ),
  'newline' => "\r\n"
);
```

# まとめ
usernameとpasswordがどこで確認できるのか忘れることがあったので、まとめてみました。
誰かの参考になれば幸いです。
今更ながらJavaScriptを勉強し直す 4. JavaScriptのライブラリを軽く使ってみる

# はじめに
[前回](https://qiita.com/myktmht/items/04da17d84e67cf740ec6)に引き続き、JavaScript(以降JS)の復習をしていきます。
今回は、JSの便利なライブラリやフレームワークについてまとめていきます。
どんなライブラリやフレームワークがあるのかを学んでいきます。

# ライブラリとは
汎用性の高い複数のプログラムを再利用可能な形でひとまとまりにしたもので、他のプログラムに何かの機能を提供するコードの集合体のこと。
簡単に言うと、**JSで開発を行うのを簡単にするツール**のことである。

# どんなライブラリがあるのか
JSのライブラリは流行り、廃りの流れがとても速い。
代表的なライブラリだけではなく、JSで書けるフレームワークも用意されているので、どんなものがあるのか確認してみる。
また、JSで書いた時とそれぞれ書き方がどう違うのかも比較していく。

```javascript:JSでクリックイベントを書く場合
let btn = document.getElementByID("title");
btn.addEventListener("click", function() {
  console.log("Hello world");
});
```

# jQuery

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414101/8c23937c-9f7b-221a-83a2-43442be5de44.png)

[前回](https://qiita.com/myktmht/items/04da17d84e67cf740ec6)学んだDOM操作(DOM要素の取得や追加削除など)をもっと短く書ける。
現在、やや下火傾向ではあるが、手軽に扱うことから未だに根強い人気を誇る。
webサイトを制作したい場合は、jQueryの知識が必要になる（らしい）。

```js:jQueryでクリックイベントを書く場合
$(function() {
  $("#button").on("click", function() {
    console.log("Hello world");
  });
});
```

# React

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414101/090fda15-19b8-e476-b1c3-1848e78cc504.png)

Facebookが開発したライブラリ。
`仮装DOM`の概念によって、より速い高速なアプリケーション実装が実現できる。
AndroidやiOSに対しても`React Native`を使用すればReactを適用でき、柔軟性も高いことから、最近大きく人気が増している。
書き方は、JSとHTMLを合わせて書く。

```jsx:Reactでクリックイベントを書く場合
class Hoge extends React.Component{
    render(){
        return (<div onClick={() => console.log('Hello world') }>
        </div>)
    }
}
```

### 仮装DOMとは？
jQueryの場合、データを更新したらDOMを操作してビューを更新する（クラスに追加や削除など）。
実は、DOMを直接操作するのは思っているよりも処理が遅い。
そこで、構造化した仮のDOMを作成し、新しくデータを更新したら仮装DOMの差分だけをDOMに反映されるのが、仮装DOMを使った基本的な考え方。
これにより、処理を早くすることができる。

# Vue.js

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414101/5a78f65d-bbbf-23e0-f334-5ab35f3572bd.png)

近年JSのフレームワークとして使用される現場がとても増え、人気。
Reactと同様に仮装DOMの概念があり、冗長な記述を減らして、HTML、CSSを中心としたWebアプリ開発が可能。

```js:Vue.jsでクリックイベントを書く場合
new Vue({
  el: '#button',
  methods: {onClick: function() {
    console.log('Hello world');
  }}
})
```

# スクールではjQueryを学んだ。なぜ？
私が通ったスクールでは、上記の3つからjQueryが使用され以降の学習の中心となりました。
理由としては、以下の3つをあげていました。

**1. 歴史があるのでリファレンス（参考文献）が多くあり、学習を進めるのが容易**
**2. 機能が限定的でとっつきやすい**
**3. まだまだ使われている現場が多い**

近い将来は残りの2つの方が使われる頻度が多くなるかと思うのだが、まだ勉強できていないのが事実。
触って見た感想などを記事にできればいいかなと思います。

早く知りたい方は、他の方の記事を見ていただければと思います。

**:warning:次回以降はjQueryの復習となります。**


# 今回はここまで！
[次回](#) に続く（現在製作中）
【機械学習】Create MLモデルをXcodeのPlaygroundで作ってみた

環境メモ
⭐️Mac OS Mojave バージョン10.14
⭐️Xcode11.2

# Create MLとは
Core MLのモデルを作成するためのmacOSの新フレームワークです。
Macで独自の機械学習モデルを作成してトレーニングします。

XcodeのPlaygroundを使って、学習モデルを作ります。

↓↓↓実際に動かした動画
https://twitter.com/nonnonkapibara/status/1222857714319024129
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🍎機械学習🍎<br>macOSのXcode「Playground」を使って<br>「機械学習モデル」😺を作ってみたよぉ🏖️<br>学習用のにゃんこ画像😻とワンコ画像🐶をセットして<br>簡単にできたぁ😊<a href="https://twitter.com/hashtag/CreateML?src=hash&amp;ref_src=twsrc%5Etfw">#CreateML</a> <a href="https://twitter.com/hashtag/Xcode?src=hash&amp;ref_src=twsrc%5Etfw">#Xcode</a><a href="https://t.co/t9sRBCMVmr">https://t.co/t9sRBCMVmr</a> <a href="https://t.co/HnKF20bipE">pic.twitter.com/HnKF20bipE</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1222857714319024129?ref_src=twsrc%5Etfw">January 30, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


#<font color="Magenta">Qiitaの容量オーバーで画像が貼り付けられなくなりました。（errorとなる）</font>

続きは、「はてなブログ」に記載してます↓
[かぴばらさんの覚書ブログ nonkapibara](https://nonkapibara.hatenablog.com/entry/2020/01/30/210343)


<br>
<br>
旧Siv3Dで120Hzなどの高リフレッシュレート環境でも60FPSを保ちたい

## はじめに（注意）

本記事の内容は **旧Siv3D** に関するものです。

最新の [OpenSiv3D](https://siv3d.github.io/) ではフレームレートを指定する機能が用意されています。ですので本記事のような対策をする必要はありません。

## 経緯と目的

最近は 120Hz や 144Hz などの高リフレッシュレートの PC モニタが普及してきています。一方、ゲーム開発では画面の更新頻度を秒間 60 回（60 FPS）とする場合が多いと思います。

旧Siv3D ではゲームループの FPS 制御を `System::Update()` 関数で行っていますが、 ユーザーがその FPS を指定することはできず、モニタのリフレッシュレートと同じになります。そのため、ゲームの動作を 1 フレーム ＝ 1/60 秒としてフレーム単位で管理しているような場合、例えば 120Hz の環境では動作が倍速になってしまいます。

この対策として

1. ゲームの動作をフレーム単位でなく時間単位で管理する
2. 60FPSになるようゲームループの速度を自力で調整する

のふたつが思いつきます。ですが既存のプロジェクトに対して今更 1. をするのは面倒なので、2. の方法を考えます。

## 案A

今普及してきている高リフレッシュレートの環境のうち大部分は 120Hz くらいとみなし、そのような環境ではゲームの更新頻度を半分にします。

`Profiler::FPS()` がモニタのリフレッシュレートと同じくらいになるため、この値が大きければ高リフレッシュレート環境とみなし、ゲームループの中の **更新処理のみ** 2回に1回スキップします。（更新処理と描画処理が分離できていないとやり辛いかもしれませんが）。

処理をとばすだけなので、お手軽なんじゃないでしょうか。

```cpp
#include <Siv3D.hpp>

void Main()
{
	// 3秒くらいFPSが安定するのを待つ
	Stopwatch timerWait{ true };
	while (System::Update() && timerWait.elapsed() < 3s)
	{
		PutText(Format(L"リフレッシュレート確認中... ", Profiler::FPS()));
	}

	// モニタのリフレッシュレート ≒ 現在のFPS
	const int RefreshRate = Profiler::FPS();

	while (System::Update())
	{
		if (RefreshRate > 70 && (System::FrameCount() % 2 == 1))
		{
			// なにもしない
			// （高リフレッシュレート環境で更新頻度を半分にする）
		}
		else
		{
			// ゲームの更新処理
			// ...
		}

		// ゲームの描画処理
		// ...
	}
}
```

## 案B

ゲームループの最後に、60FPS になるよう良い感じに待機します。古代からあるやり方かなと思います。

```cpp
#include <Siv3D.hpp>

class FPSControl
{
	Stopwatch64 m_sw{ true };

public:
	void wait(int frameRate = 60)
	{
		// 前回からの経過時間が1フレーム当たりの時間以内だったら、
		// 残り時間はスリープする
		if (m_sw.ms() < 1000.0 / frameRate)
		{
			System::SleepAccurately(1000.0 / frameRate - m_sw.ms());
		}
		m_sw.restart();
	}
};

void Main()
{
	FPSControl fpscontrol;

	while (System::Update())
	{
		// ゲームの更新処理
		// ...

		// ゲームの描画処理
		// ...

		// FPS調整のために待機する
		fpscontrol.wait(60);
	}
}
```

## おわりです

とりあえず案AかBのどちらかを既存のプロジェクトに適用すれば、倍速になるケースをかなり抑えられるはずです。

実際の高リフレッシュレート環境で動作確認をしてないですが、だいたいこんな感じだと思います。
xdebug インストール

## ダウンロードページ

[:floppy_disk: ダウンロード (xdebug.org)](http://www.xdebug.org/download.php)


### php-cli 向け
```
PHP 7.4 VC15 (64 bit) (SHA256: ***)
PHP 7.4 VC15 (32 bit) (SHA256: ***)
```

## apache module 向け
```
PHP 7.4 VC15 TS (64 bit) (SHA256: ***)
PHP 7.4 VC15 TS (32 bit) (SHA256: ***)
```


上記からダウンロードしたものを extension_dir にいれる

以下を追記

```ini:php.ini
[xdebug]
zend_extension=xdebug
;xdebug.coverage_enable=1
;xdebug.default_enable=1
;xdebug.profiler_enable=1
;xdebug.profiler_output_dir="/tmp"
;xdebug.remote_autostart=1
;xdebug.remote_enable=1
;xdebug.remote_host=localhost
;xdebug.remote_port=9000

```
Qiitaはじめました。テックエキスパート70期生です！よろしくだゾ！！

今日、ようやっと基礎カリキュラムを合格しました。
本試験５２点だったときは終わったと思ってたんですけども。。。
毎朝の努力は裏切らない！！
77点で結構ギリギリでした。

で、今日からJavaScriptの学習に入った訳ですが、一言
Rubyと大して変わらんやんww

これから週に何回か投稿していきます。
誰か見て絡んでくれたら嬉しいかも！

っていうわけで短いですが、今日は終わり。
この記事がいつか宝物になる日まで走ります！！
[Microsoft Edge]MutationObserverでattributeFilterを使った場合にSyntax Errorになる問題について

# 概要
Firefox, Chrome等において`MutationObserver`で`attributeFilter`を使った場合には動作するが、Edgeでは`Syntax Error`が発生した際の覚書

# コード
```js

const ob = new MutationObserver((mutations, observer)=> {
  console.log(mutations, observer)
})

ob.observe(document, {
  childList: true,
  subtree: true,
  attributeFilter: ["height"],
})
```
子要素の追加や削除高さの変更を見ようとこのようなコードを書いたが、このコードはEdgeだと構文エラーになる
※`attributeFilter: ["height"]`を指定しても検知される変更は`Element.height`の値だけなのでスタイルの変更や内容の変化からの高さの変化自体は検知されません。

# 修正版

```js
const ob = new MutationObserver((mutations, observer)=> {
  console.log(mutations, observer)
})

ob.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  attributeFilter: ["height"],
})
```

`attributes: true` この一行を追加したら問題なくなる

# 原因

Stack OverFlowで下記の回答を見つけた。

> With a MutationObserver, it's possible to filter attributes, but only if you are observing element attributes to begin with. Therefore the option attributeFilter is only applicable if attributes is set to true.

> If you specify an attributeFilter without setting attributes to true, then IE11 will throw a syntax error, while Chrome and Firefox will just silently ignore attributeFilter.

> To resolve the syntax error, either set attributes to true or remove the attributeFilter.

https://stackoverflow.com/questions/50593385/mutationobserver-syntax-error-on-ie-11

つまり`attributeFilter`を使うには`attributes`を有効にしておく必要がある。
ChromeやFirefoxでは`attributes`を有効にせずに`attributeFilter`を利用すると`attributeFilter`の設定をエラー出さずに無視するが、IE11(Edgeでも)では`syntax error`になるとの事。

確かに`attributes`を有効にするとEdgeでエラーは出なくなるのだが、[MDN](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit/attributeFilter)では
> If this property is specified, there's no need to also set attributes to true, as it's implied

とのように`attributeFilter`を指定していれば`attributes`を`true`にする必要は無いとの記述を見つけたので試してみた。

# 検証

|ブラウザ| attributeFilterとattributes|attributeFilterのみ|
|-------|---------------------------|-------------------|
|Edge   | 問題なし                   | Syntax Error      |
|Chrome | 問題なし                   | 問題なし            |
|Firefox| 問題なし                   | 問題なし            |

という結果になった。

# あとがき
今回の検証ではChromium ベースでない古いEdgeを利用したので、新しい方ではChromeやFirefoxと同じ挙動になるかも。
とりあえず、`attributeFilter`使う際は`attributes`も設定しておくと良いかも。
アニメーションに武器などのオブジェクトを追加、交換する

初心者なので他の方法もあるかと思いますが、
武器を持ち変えるアニメーションをどうしたらいいのかと考えてやりました。

１　既存のhumanのオブジェクトの子要素に武器（stick)を追加
2  既存のアーマチュア(ボーン）など追加したい場所(ここでは右腕)の子要素に武器などを設定（ドラッグアンドドロップ）
3  サイズなどを合わせる
4  アニメーションさせて連動して動いてくれるか確認

![武器装備.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560721/a741b50d-d050-90e3-cad9-1c27c1afd803.png)

![武器装備1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560721/5f8eeb0d-da3a-c305-2057-e6bb431620e7.png)



![武器装備3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560721/bf8b4369-50bb-fa07-75e9-a1a4f0e5b1cc.png)

腕の先に空のGameObjectをつけておけば後はスクリプト で武器をInstantiate
すればいいと思います。
Googleサービスアカウント取得の際に発行されるjsonファイルの認証情報を.envに設定。

下記サイトを参考にサービスアカウントを取得した際に
認証キーが入ったjsonファイルをダウンロードします。

https://sukohi.blogspot.com/2017/05/laravel-google.html

``` hoge.json

{
  "type": "xxx",
  "project_id": "xxx",
  "private_key_id": "xxx",
  "private_key": "xxx",
  "client_id": "xxx",
  "auth_uri": "xxx",
  "token_uri": "xxx",
  "auth_provider_x509_cert_url": "xxx",
  "client_x509_cert_url": "xxx"
}

```

GoogleカレンダーAPIにて認証を行う際のコード

``` googleCalendarService.php

        $client = new \Google_Client();
        $client->setApplicationName('Google Calendar API PHP Quickstart');

        $client->setScopes([
            \Google_Service_Calendar::CALENDAR,
            \Google_Service_Calendar::CALENDAR_EVENTS,
        ]);

        $client->setAuthConfig(pass/hoge.json); //JSONのファイルパスとJSONファイル
        $client->setAccessType('offline');
        $client->setPrompt('select_account consent');

        $service = new \Google_Service_Calendar($client);
        return $service;

```

jsonファイルの中身はこんな感じ。
GitHubにそのままgitにpushするのはマズイ。

### ①config配下に設定ファイルを作成

``` config/google-account.php

return [

    'account' => [
        
        'type'=>env('TYPE'),
        'project_id'=>env('PROJECT_ID'),
        'private_key_id'=>env('PRIVATE_KEY_ID'),
        'private_key'=>env('PRIVATE_KEY'),
        'client_email'=>env('CLIENT_EMAIL'),
        'client_id'=>env('CLIENT_ID'),
        'auth_uri'=>env('AUTH_URI'),
        'token_url'=>env('TOKEN_URI'),
        'auth_provider_x509_cert_url'=>env('AUTH_PROVIDER_X509_CERT_URL'),
        'client_x509_cert_url'=>env('CLIENT_X509_CERT_URL'),

    ],
];
```

### ②.envに認証情報を記述

``` _.env

TYPE=
PROJECT_ID=
PRIVATE_KEY_ID=
PRIVATE_KEY=
CLIENT_EMAIL=g
CLIENT_ID=
AUTH_URI=
TOKEN_URI=

```

### ③認証を行う際のコードを修正

``` googleCalendarService.php

        $client = new \Google_Client();
        $client->setApplicationName('Google Calendar API PHP Quickstart');

        $client->setScopes([
            \Google_Service_Calendar::CALENDAR,
            \Google_Service_Calendar::CALENDAR_EVENTS,
        ]);

        $googleDataArray = \Config::get('google-account.account'); //追加
        $client->setAuthConfig($googleDataArray);//書き換え
        $client->setAccessType('offline');
        $client->setPrompt('select_account consent');

        $service = new \Google_Service_Calendar($client);
        return $service;
```


#### 補足：json形式に変換するのかと勘違いしてましたが変換は不要です。
型が違う！って怒られちゃいます。

```googleCalendarService.php

$g = json_encode($googleDataArray);
$client->setAuthConfig($g);

```
CSSセレクタの優先度(詳細度)

CSSセレクタをなんとなく使ってきたため、説明しようとしたときに混乱したので整理。
詳細度で検索かけると正しい内容が出てくる一方で優先度、優先順位で検索かけると間違った情報が出てくるので困りもの。

# 参考サイト
[詳細度 - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/Specificity)
[Specifishity :: Specificity with Fish](https://specifishity.com/)

# 結論
以下の順にCSSが反映される。
1で決まらなければ2、2で決まらなければ3...と順に判定していく

1. `!important`規則が使用されているもの
1. インラインスタイルが使用されているもの
1. IDセレクタ(`#id`など)の数が最も多いもの
1. クラスセレクタ(`.class`など)、属性セレクタ(`[attr]`など)、疑似セレクタ(`::hover`, `:nth-child()`など)の数が最も多いもの
1. 要素セレクタ(`div`, `input`など)の数が最も多いもの
1. より出現が遅いもの

# 検証

CSSセレクタ同士の比較と出現順による影響

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245491/ee550c7a-22a0-d814-24e0-3b29396e91d5.png)

```html
<html>
<head>
  <style>
    #simple-sample .red {
      color: red !important;
    }
    #simple-sample #yellow {
      color: darkgoldenrod;
    }
    #simple-sample :nth-child(2) {
      color: blue;
    }
    #simple-sample [attr] {
      color: green;
    }
    #simple-sample .lightseagreen {
      color: lightseagreen;
    }
    #simple-sample div {
      color: purple;
    }

  </style>
</head>
<body>
<div id="simple-sample">
  <div>
    <span>要素セレクタの優先度が一番低い</span>
    <div>
      <span>要素セレクタの次に疑似セレクタなど</span>
      <div attr>
        <span>疑似セレクタと同じ優先度だが、後に記載されているものが優先される</span>
        <div class="lightseagreen">
          <span>クラスセレクタと同じ優先度だが、後に記載されているものが優先される</span>
          <div id="yellow">
            <span>要素セレクタ、疑似セレクタ、クラスセレクタの次にIDセレクタ</span>
            <div style="color: orangered">
              <span>セレクタを頑張って書いても基本的にインラインスタイルに負ける</span>
              <div class="red">
                <span>!importantはインラインスタイルすら無視する</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
</body>
</html>

```

あるセレクタがいくら多くても、上位のセレクタには勝てない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245491/ba244ec7-d39d-44ea-de31-a0a0dbae4d56.png)

```html
<html>
<head>
  <style>
    #many-sample :not(.a):not(.b):not(.c):not(.d):not(.e):not(.f):not(.g):not(.h):not(.i):not(.j):not(.k):not(.l):not(.m):not(.n) {
      color: blue;
    }
    #many-sample .zzz {
      color: green;
    }

    #many-sample #id-selector {
      color: red;
    }

  </style>
</head>
<body>
<div id="many-sample">
  <div>
    <span>とても長いセレクタの影響を受ける</span>
  </div>
  <div class="zzz">
    <span>同じレベルの要素数が少ないと負ける</span>
  </div>
  <div>
    <span id="id-selector">上位のセレクタ(idセレクタ)には勝てない</span>
  </div>
</div>
</body>
</html>
```
1/30 授業ノート

#復習
**範囲：教科書(HTML5&CSS3標準デザイン講座)P14,16**
・要素→開始タグと終了タグに囲まれた範囲のこと
　ex:)```<p>この範囲</p>```
・最初の１行目に```<!DOCTYPE html>```などの宣言=**DTD(Document Type Definition)**を書く
・開始と終了のタグで括られた範囲、まとまりのことをボックスと呼ぶ
・head要素→ページ全体の情報(文字コードやキーワードなどの補足情報、検索エンジン向けの情報など)を記述。ブラウザに表示されない
・body要素→ページの中身を記述。ブラウザに表示される
・title要素→HTML文書のタイトルを記述。SEO対策の上でも重要
・meta要素→文字コード・文書の概要・キーワード等ブラウザに表示されない文書情報を記述
・属性→開始タグにつける

#今日習ったことまとめ
**範囲：教科書(HTML5&CSS3標準デザイン講座)P46～**
　ex:)charset属性→文字コードをつける場合```<meta charset=”ja”>```
・aタグ→aはAnchorタグのこと。
・絶対パス→httpから始まるWebサイトのアドレス(=URL)でファイルの場所を指定する方法
　主に違うサーバに存在するファイルを指定するときに使う
　ex:)```http://www.yahooo.co.jp```
・相対パス→現在のファイルから目的のファイルまでの相対的な位置関係を指定する方法
　サイト内部(同一サーバー)のファイルを指定するときに使う
　ex:)```index/style.css```
・table→tableタグで始まる表組み。見出し→th、中身→tdタグに表記。
　ex:)
```<table>
　<tr><th>なまえ</th><td>にゃんこ</td></tr>
　<tr><th>もよう</th><td>さばとら</td></tr>
　<tr><th>せいかく</th><td>かげき</td></tr>
</table>```
記述すると以下のようになる↓
<table>
　<tr><th>なまえ</th><td>にゃんこ</td></tr>
　<tr><th>もよう</th><td>さばとら</td></tr>
　<tr><th>せいかく</th><td>かげき</td></tr>
</table>
**※tableタグのborder属性について
　→```<table border=”1″>```という書き方があり、HTMLでも表の枠組みを表示出来るような記述方法があるが、構文エラーを起こすため基本はCSSで表記する。
エラー詳細:The width attribute on the table element is obsolete. Use CSS instead.(table要素内でのborder要素は廃止されました。代わりにCSSを使ってください。)**


・説明（説明）リスト→説明(Definition:定義/Description:説明)リスト。
　dtタグとddタグは必ずセットになっていなければならない。
　ex:)
```<dl>
　<dt>見出し</dt><dd>解説</dd>
　<dt>見出し</dt><dd>解説</dd>
　<dt>見出し</dt><dd>解説</dd>
</dl>```
記述すると以下のようになる↓
<dl>
　<dt>見出し</dt><dd>解説</dd>
　<dt>見出し</dt><dd>解説</dd>
　<dt>見出し</dt><dd>解説</dd>
</dl>

#感想
Photoshopの操作については悲鳴あげたくなるけど(写真専門の授業じゃないから仕方ない)、
マークアップの部分は忘れてたりあやふやな状態の知識があぶりだされたので良かった。
予習大好きだけど復習をあまりしない(授業=復習&質問タイムと捉えてる)から、いい機会だった。
復習真面目にやろうな。
PythonistaでSCNMaterialのlightingModelを指定する

<img width="368" alt="C4826DB1-F6F1-482A-9F18-57A5E837144A.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/7f1bc015-16ca-605b-9a81-23563f656763.jpeg">

Pythonista では swift の struct や定数？にうまくアクセスできなくてモデルの質感を大きく変えられる SCNMaterial の lightingModel を変更できないと思っていたのですが、方法が見つかったのでご紹介します。

# setLightingModelName_(string name)

lightingModel は SCNMaterial のプロパティですが、変更する時は setLightingModelName_ 関数を使います。

引数は文字列で下記の文字列が指定可能です。

```python
class SCNLightingModel:
	blinn = 'SCNLightingModelBlinn'
	constant = 'SCNLightingModelConstant'
	lambert = 'SCNLightingModelLambert'
	phong = 'SCNLightingModelPhong'
	physicallyBased = 'SCNLightingModelPhysicallyBased'
	shadowOnly = 'SCNLightingModelShadowOnly'
```

# サンプルソース

```python:scenekit03.py
import objc_util
from objc_util import *
import ui

load_framework('SceneKit')

SCNView,SCNNode,SCNScene,SCNCamera,SCNLight,SCNBox,SCNMaterial = map(ObjCClass, ['SCNView','SCNNode','SCNScene','SCNCamera','SCNLight','SCNBox','SCNMaterial'])

class SCNLightingModel:
	blinn = 'SCNLightingModelBlinn'
	constant = 'SCNLightingModelConstant'
	lambert = 'SCNLightingModelLambert'
	phong = 'SCNLightingModelPhong'
	physicallyBased = 'SCNLightingModelPhysicallyBased'
	shadowOnly = 'SCNLightingModelShadowOnly'
	

def main():
	main_view = ui.View()
	main_view_objc = ObjCInstance(main_view)
	
	# View
	scene_view = SCNView.alloc().initWithFrame_options_(((0, 0),(400, 400)), None).autorelease()
	# UIView.autoresizingMask = flexibleWidth(2) | flexibleHeight(16)
	scene_view.setAutoresizingMask_(18)
	scene_view.setAllowsCameraControl_(True)
	
	scene = SCNScene.scene()
	node_root = scene.rootNode()
	
	# material
	material = SCNMaterial.material()
	material.setLightingModelName_(SCNLightingModel.physicallyBased) 
	material.diffuse().setColor_(UIColor.redColor().CGColor())
	
	# box geometry
	geom_box = SCNBox.boxWithWidth_height_length_chamferRadius_(1.0,1.0,1.0,0.2)	
	geom_box.setMaterials_([material])
	node_box = SCNNode.nodeWithGeometry_(geom_box)
	node_box.setPosition((-0.5,0.5,-0.5))
	node_root.addChildNode_(node_box)
	
	# camera
	camera = SCNCamera.camera()
	node_camera = SCNNode.node()
	node_camera.setCamera(camera)
	node_camera.setPosition((0,0,5.0))
	node_root.addChildNode_(node_camera)
	
	# Light
	light = SCNLight.light()
	light.setType_('omni')
	light.setColor_(UIColor.whiteColor().CGColor())
	node_light = SCNNode.node()
	node_light.setPosition((2.0,2.0,2.0))
	node_light.setLight_(light)
	node_root.addChildNode_(node_light)
	
	scene_view.setScene_(scene)
	
	main_view_objc.addSubview_(scene_view)
	
	main_view.name = 'scene kit'
	main_view.present()
	
main()
```

# 謎

SCNMaterial の struct LightingModel と SCNLightingModel の関係は謎。

# 参考

- [SCNMaterial](https://developer.apple.com/documentation/scenekit/scnmaterial)
- [SCNMaterial.LightingModel](https://developer.apple.com/documentation/scenekit/scnmaterial/lightingmodel)
- [SCNLightingModel](https://developer.apple.com/documentation/scenekit/scnlightingmodel)