OmniAICreator/Qiita-1.07M huggingface dataset:
Grafana + Loki + Promtailでログの可視化

# この記事の概要

- ちょっと気になっていたLokiがGAになったので触ってみる
- アプリケーションはサーバーで稼働しているものを対象とする
  - →Promtailはアプリケーションサーバーに構築
- Lokiはデータ永続化の観点で監視用サーバーに構築

※kubernetesでもpersistent volumeを使えばLokiを載せられるので時間があればチャレンジ

# Document

- [promtail](https://github.com/grafana/loki/tree/master/docs/clients/promtail)
- [loki](https://github.com/grafana/loki)

# Lokiの構築

### 1. binaryを以下のページからダウンロード
https://github.com/grafana/loki/releases

### 2. サーバーにscp等で送信

### 3. 解凍＆配置

```
$ unzip loki-linux-amd64.zip
$ mkdir -p /opt/loki/{bin,conf}
$ cp loki-linux-amd64 /opt/loki/bin/loki
```

### 4. 設定ファイルを配置

```
$ cd /opt/loki/conf
$ curl https://raw.githubusercontent.com/grafana/loki/v1.4.1/cmd/loki/loki-local-config.yaml -o loki-config.yaml
```

### 5. 起動

```
$ vi /etc/systemd/system/loki.service
[Service]
ExecStart=/opt/loki/bin/loki -config.file=/opt/loki/conf/loki-config.yaml

$ systemctl start loki
```

# promtailの構築

### 1. binaryを以下のページからダウンロード
https://github.com/grafana/loki/releases

### 2. サーバーにscp等で送信

### 3. 解凍＆配置

```
$ unzip promtail-linux-amd64.zip
$ mkdir -p /opt/promtail/{bin,conf}
$ cp promtail-linux-amd64.zip /opt/promtail/bin/promtail
```

### 4. 設定ファイルを配置

```
$ cd /opt/promtail/conf
$ curl https://raw.githubusercontent.com/grafana/loki/v1.4.1/cmd/promtail/promtail-docker-config.yaml -o promtail-config.yaml

# 修正ポイントだけ記載
$ vi promtail-config.yaml
...
clients:
  - url: http://<監視用サーバー名>:3100/loki/api/v1/push
...
      __path__: <log file>
...
```

### 5. 起動

```bash
$ vi /etc/systemd/system/promtail.service
[Service]
ExecStart=/opt/promtail/bin/promtail -config.file=/opt/promtail/conf/promtail-config.yaml

$ systemctl start promtail
```

# Grafanaの構築

kubernetes上に構築
※ダッシュボード等のデータの永続化をしたい場合は[こちら](https://qiita.com/rhirabay/items/464adbe268837e9de846)をご参考ください

最新のGrafanaを使用していればLokiはデフォルトで有効になっているはず！
<img width="621" alt="Screen Shot 2020-05-03 at 17.58.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/d6d74b6b-43f1-c0ab-e2ec-6eee824c5c32.png">

- URLだけ設定すればとりあえず使える！
- localhostの部分は適宜サーバーやkubernetesのservice名等に置き換えてください


# Tips

ここからはやりたいことベースにどうすれば実現できるかを記載

### 特定のログを送らない

- pipeline_stagesで`action: drop`で定義
- selectorはgrafanaとかで想定通りのログが抽出されるか確認するのがベター（自分への戒め）
- [参考](https://github.com/cyriltovena/loki/blob/master/docs/clients/promtail/stages/match.md#example)

```yaml
scrape_configs:
- job_name: <job_name>
  pipeline_stages:
  - match:
      selector: '{app="<app>"} |~ ".*<Ignore regex>.*"'
      action: drop
```

### ログをパースしてメトリクス化する

サンプルとしてログからレスポンスタイムを抽出して、メトリクス化してみます

```plaintext:ログサンプル
API end. [200] /path in 68 ms
```

Grafanaにて、以下のようにクエリを書くことで、ステータスごとパスごとのメトリクスにできます！

```plaintext:レスポンスの平均のサンプル
avg_over_time(
{job="<job_name>"} 
 |~ "API end"
 | regexp "API end. \\[(?P<status>[0-9]+)] (?P<path>[^ ]+) in (?P<response_time>[0-9]+)"
 | unwrap response_time [1m]
 ) by (status, path)
```

このblogが参考になりました
https://grafana.com/blog/2020/10/28/loki-2.0-released-transform-logs-as-youre-querying-them-and-set-up-alerts-within-loki/
Flutterで行の両端にWidgetを配置する方法

# やりたいこと
`Column` の左端と右端にそろえて `Widget` を配置させたい。

こんな感じで。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30620/a832ca96-6751-7d64-1844-89cc05515d4a.png" width=250 />



# 実装

```dart

Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
    Text("デモ"),
    Image.asset(
    "images/demo.png",
    width: 120.0,
    ),
],
),
```
GitLab (GitHub) とGlitchを同期する

## 2020/6/10追記
2020/6/9のGlitchメンテナンスにより、本記事のやり方でGitLabと同期できなくなった模様です...T^T
配備されたコンテナが載っているホストのせいかなぁ...。ホストガチャだったら勘弁してほしい...。

## はじめに
[glitchのgitにローカルリポジトリを反映する](https://qiita.com/msquare33/items/1deaaeab86612395ca74) 
この記事にも書いた通り、GlitchはなぜかGitLabからインポートすることができない。しかし、無理やりインポートする方法を見つけたので、備忘として残す。また、インポートするだけでなく、GitLab側のPushをHookしてGlitchに自動デプロイする方法も記載。

### GitLabリポジトリのインポート
#### 1. アクセストークン取得（GitLab）
GitLabのSettings-> Access Tokensからトークンを取得する。この時に指定するScopesはread repositoryをチェックする。
![scr01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82651/cde2a9cf-4797-f59e-a091-99238c1e94e8.png)

#### 2. Glitchプロジェクトの作成
Glitch側で適当なプロジェクトを作成。下記例では、hello-webpageを新規に作成。
![scr02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82651/35ac7598-77f3-9379-4e64-dbeb63692e1b.png)

#### 3. Terminalにてgitコマンド実行
2のプロジェクトの作成が完了したら、ターミナルを開き、コマンドを実行する。
![scr04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82651/59e03f95-ec8b-868e-c18e-f248e78fef5f.png)

##### 3.1. git remote add
```sh
$ git remote add origin https://[GitLab ID]:[Access Token]@gitlab.com/*****/*****.git
```
[GitLab ID]、[Access Token]、\*\*\*\*\*/\*\*\*\*\*.gitは自分の環境に合わせて修正。

##### 3.2. git fetch（これは飛ばしてOK）
```sh
$ git fetch origin master
```

##### 3.3. git reset
```sh
$ git reset --hard origin/master
```
##### 3.4. refresh
```sh
$ refresh
```
下図の様にGitLabの内容が正常に反映されているはず。
![scr09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82651/3780b4af-c66c-4168-f890-750f04bbabe6.png)


### GitLabリポジトリの同期
GitLabからGlitchに正常にインポートすることはできたが、このままではGitLabの方を修正してもGlitchには反映されない。そこで、GitLabのWebHooksを使ってmasterブランチにpushされた場合にGlitchのソースを強制的にresetし、refreshするプログラムを組んでみた。
GitLabからGlitch上のAPIを呼び出して自身を更新するという結構強引な方式。手順は以下の通り。
#### 1. テンプレートプロジェクトのフォーク（GitLab）
ここのプロジェクトをフォークまたはクローンして新しいプロジェクトを作成する。
https://gitlab.com/michito.ichimaru/glitch-template

#### 2. GitLabリポジトリのインポート（Glitch）
上述しているGitLabリポジトリのインポートの手順に従い、1で作成したプロジェクトをインポートする。

#### 3. .env修正（Glitch）
Glitchの.envにSECRETを追記する。内容は適当な文字列でOK
![scr11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82651/a60369ee-ae94-33a1-1542-c1a133eee1ea.png)


#### 4. WebHooks設定（GitLab）
GitLab側でWebHooksの設定を実施する。入力パラメタは次の通り

|  パラメタ  |Center align |
|:--|:--|
| URL  | 2でインポートしたGlitchのURL + /api/v1/git |
| Secret Token  | 3で設定した文字列 |
| Push events  | チェック  |
| repository   | master  |
![scr12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82651/01ca2c90-2e63-de08-8e1a-55d86c754cd0.png)
これで設定は完了。

#### 5. GitLabリポジトリのmasterにpush（GitLab）
GitLab側のmasterにpushするか、masterにマージすると自動的にGlitch側も更新されるようになる。

### 参考
[Continuous Deployment to Glitch via GitHub Webhooks](https://healeycodes.com/glitch/github/tutorial/javascript/2019/05/06/glitch-to-github-via-webhook.html)
Laravel でサービス(Service)クラスの作り方

#やりたいこと
Request→Controller→Service→Model or Repository
のようにビジネスロジックの処理箇所としてServiceクラスを作成する


#やりかた
app配下に`Services`ディレクトリ作成

`HogeService.php`(名称は何でもいい)を作成

```php:app/Services/HogeService.php
<?php

namespace App\Services;

class HogeService
{
    public function hoge()
    {
          echo 'hoge';
    }
}
```

あとはControllerで呼び出すだけ
コンストラクタインジェクションまたは、メソッドインジェクションします

```php:HogeController
<?php

namespace App\Http\Controllers;

use App\Services\HogeService;

class HogeController extends Controller
{
    private $hoge;
    public function __construct(HogeService $hoge_service)
    {
        $this->hoge = $hoge_service
    }

    public function index(HogeService $hoge_service)
    {
        $this->hoge->hoge();
        $hoge_service->hoge()
    }
}

```

AppserviceProviderに記載する手順の記事が出たりしますが
公式または翻訳の通り、基本的には書かなくても問題ないです。
インターフェースをDIしたりする際には必要です。

<img width="905" alt="スクリーンショット 2020-05-03 22.46.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174757/a0c53003-2cd4-f045-14b6-783b71284388.png">


https://qiita.com/minechan1234/items/2cc7c69875fafb2fdae9
https://qiita.com/ekzemplaro/items/354166c8612e45dbe822
AtCoder Beginner Contest 166 参戦記

# AtCoder Beginner Contest 166 参戦記

## [ABC166A - A?C](https://atcoder.jp/contests/abc166/tasks/abc166_a)

2分半で突破. 書くだけ. コードテストが詰まってて時間がかかった.

```python
S = input()

if S == 'ABC':
    print('ARC')
elif S == 'ARC':
    print('ABC')
```

## [ABC166B - Trick or Treat](https://atcoder.jp/contests/abc166/tasks/abc166_b)

2分半で突破. B問題にしては難しいような? 持ってるか持っていないかをテーブルで管理して、持っている人は持っているとテーブルに書き込んで、最後に持っていない人を集計するだけ.

```python
N, K = map(int, input().split())

t = [0] * N
for _ in range(K):
    d = int(input())
    A = list(map(int, input().split()))
    for a in A:
        t[a - 1] += 1
print(t.count(0))
```

## [ABC166C - Peaks](https://atcoder.jp/contests/abc166/tasks/abc166_c)

6分半で突破. テーブルに隣接の展望台の最高峰を更新していって、最後に隣接の展望台の最高峰と高さを比較するだけ.

```python
N, M = map(int, input().split())
H = list(map(int, input().split()))

t = [0] * N
for _ in range(M):
    A, B = map(int, input().split())
    t[A - 1] = max(t[A - 1], H[B - 1])
    t[B - 1] = max(t[B - 1], H[A - 1])

result = 0
for i in range(N):
    if H[i] > t[i]:
        result += 1
print(result)
```

## [ABC166D - I hate Factorization](https://atcoder.jp/contests/abc166/tasks/abc166_d)

6分半で突破. Aを負にするとBが負のパターンが両方正とだぶるので、Aは0以上でいいはず. 後は 10<sup>3</sup> もあれば、10<sup>15</sup> までカバーできるし、*O*(2×10<sup>6</sup>) だから TLE にもならんだろうで AC. 最初100で出して WA1 orz.

```python
X = int(input())

for A in range(1000):
    for B in range(-1000, 1000):
        if A ** 5 - B ** 5 == X:
            print(A, B)
            exit()
```

## [ABC166E - This Message Will Self-Destruct in 5s](https://atcoder.jp/contests/abc166/tasks/abc166_e)

敗退

追記: 解説PDF通りの実装. 式変形かー.

```python
N = int(input())
A = list(map(int, input().split()))

c1 = {}
c2 = {}

for i in range(N):
    c1.setdefault(i + A[i], 0)
    c1[i + A[i]] += 1
    c2.setdefault(i - A[i], 0)
    c2[i - A[i]] += 1

result = 0
for k in set(c1).intersection(c2):
    result += c1[k] * c2[k]
print(result)
```
PythonでABC166のA~Dを解く

### はじめに
今日はA~Dの4完でした。今日もCに悩まされたよ()

### A問題
[問題](https://atcoder.jp/contests/abc166/tasks/abc166_a)

**考えたこと**
if

```python
s = input()

if s == 'ABC':
    print('ARC')
else:
    print('ABC')
```


### B問題
[問題](https://atcoder.jp/contests/abc166/tasks/abc166_b)

**考えたこと**
入力がやや面倒だった。N人のリスト作って、お菓子を持ってるかを確認する。

```python
n, k = map(int,input().split())
d = []
a = []
for _ in range(k):
    d.append(int(input()))
    a.append(list(map(int,input().split())))
check = [False] * n
for i in range(k):
    for j in a[i]:
        check[j-1] = True

ans = 0
for i in range(n):
    if not check[i]:
        ans += 1
print(ans)
```

### C問題
[問題](https://atcoder.jp/contests/abc166/tasks/abc166_c)

**考えたこと**
繋がってる道の数のlistを作って大小を確認する。
高さが同じ場合の処理をしていなくて3WAも出てしまいました。ゆるしません。

```python
n, m = map(int,input().split())
h = list(map(int,input().split()))
ab = [(list(map(int,input().split()))) for _ in range(m)]

path = [0] * n
check = [0] * n
for i in range(m):
    path[ab[i][0]-1] += 1
    path[ab[i][1]-1] += 1
    if h[ab[i][0]-1] < h[ab[i][1]-1]:
        check[ab[i][1]-1] += 1
    elif h[ab[i][0]-1] == h[ab[i][1]-1]:
        continue
    else:
        check[ab[i][0]-1] += 1

ans = 0
for i in range(n):
    if path[i] == check[i]:
        ans +=1

print(ans)
```

### D問題
[問題](https://atcoder.jp/contests/abc166/tasks/abc166_d)

**考えたこと**
数学?知らない子ですね。$-1000<=a,b<=1000$くらいになるで全探索しました。

```python
x = int(input())

for i in range(-1000,1000):
    for j in range(-1000,1000):
        if i ** 5 - j ** 5 == x:
            print(i,j)
            quit()
```

### まとめ
細かいところを見落としてペナが生えたり、時間のロスが生じているので良くない。今回も、C,Dはもっと早く解けました。悔しいです。ではまた、おやすみなさい。
FlutterのGridViewをスクロールしないようにして親Containerをスクロールするようにする方法

# やりたいこと
`Container` の中に `GridView` があって、 `GridView` 内でスクロールするのではなく、 `Container` 全体をスクロールするようにする。

# 実装

`GridView` のプロパティーに

```dart
physics: NeverScrollableScrollPhysics()
```
これを設定しておけばスクロールしなくなる


以下、サンプルコード

```dart
    return Scaffold(
      appBar: AppBar(
        title: Text(
          "sample",
        ),
      ),
      body: SingleChildScrollView(
        child: Container(
          padding: EdgeInsets.all(10),
          color: Theme.of(context).primaryColor,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text("テスト1",),
                  Text("テスト2",),
                ],
              ),
              GridView.count(
                shrinkWrap: true,
                primary: true,
                padding: const EdgeInsets.all(1.0),
                crossAxisCount: 4,
                childAspectRatio: 0.85,
                mainAxisSpacing: 1.0,
                crossAxisSpacing: 1.0,
                physics: NeverScrollableScrollPhysics(),    //これをいれておくとGridView内でスクロールしなくなる
                children: _sampleContainer(context),
              ),
            ],
          ),
        ),
      ),
    );

```
ABC166をPythonで A~C問題

#はじめに
今回もAtCoder Beginners Contest 166にPythonで挑戦しました！！
B問題の出力を間違えているのに気づくのが遅れ、かなりロスしてしましました…
にしても、2日連続のABCはいいですね！！

#A問題

```Python:A.py
s = input()
if s == "ABC":
    print("ARC")
else:
    print("ABC")

```
#B問題

```Python:B.py
n, k = map(int, input().split())
d = [0] * k
sunuke = {}
for i in range(n):
    sunuke.setdefault(str(i),0)
for i in range(n):
    sunuke[str(i)] = 0

for i in range(k):
    d[i] = int(input())
    A = list(map(int, input().split()))
    for j in range(d[i]):
        sunuke[str(A[j]-1)] += 1
ans = list(sunuke.values()).count(0)
print(ans)




```
#C問題

```Python:C.py
n, m = map(int, input().split())
h = list(map(int, input().split()))
cnt = [0] * n
chk = [0] * n
ans = 0

for i in range(m):
    a,b = map(int, input().split())
    if h[a-1] > h[b-1]:
        cnt[a-1] += 1
    if h[a-1] < h[b-1]:
        cnt[b-1] += 1
    chk[a-1] += 1
    chk[b-1] += 1

for i in range(n):
    if cnt[i] == chk[i]:
        ans += 1

print(ans)
```
Minima Hopping法を用いて吸着構造を探索する

ASE (Atomic Simulation Environment) に実装されているMinima Hopping法を用いて，Pt表面上でのH<sub>2</sub>分子の吸着構造を探索してみます．この記事は[公式ドキュメントのチュートリアル](https://wiki.fysik.dtu.dk/ase/tutorials/minimahopping/minimahopping.html)を参考にして作成しました．

なおEMTを用いているのは計算速度上の理由によります．特に有機分子（C, H, O, N) については，[公式ドキュメント](https://wiki.fysik.dtu.dk/ase/ase/calculators/emt.html)で言及されているように, 単なるお遊びのモデルです．信頼性はありません．実務などで使用する場合は適切な理論を選択してください．

## スラブモデルを作成

Pt (211)表面上にH<sub>2</sub>分子を吸着させたモデルを作成します．

```python
from ase.build import surface, add_adsorbate
from ase.data import atomic_numbers, covalent_radii
from ase.visualize import view

# Ptバルク
Pt_bulk= bulk('Pt', 'fcc', a=3.9, cubic=True) 

# Pt(211)スラブ
Pt_211 = surface(Pt_bulk, (2,1,1), 3, vacuum=10, periodic=True) 
d_PtH = (covalent_radii[atomic_numbers['H']] + covalent_radii[atomic_numbers['Pt']])
z_max =  np.max(Pt_211.positions[:,2]) # Pt原子のz座標の最大値
xy_center = ((Pt_211.cell[0]+Pt_211.cell[1])/2)[0:2]

# H2分子を追加
add_adsorbate(Pt_211, molecule('H2'), d_PtH, xy_center)

# 構造を確認
view(Pt_211)
```

![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629650/023e7bbf-5931-fe7f-f3cd-9cfee1383e7b.png)

## 拘束条件を設定

`FixAtoms` クラスと `Hookean` クラスを用いて，拘束条件を設定します．
`Hookean` の拘束条件では原子間などにバネ様の力を課します．

- Ptスラブは完全に固定する
- H<sub>2</sub>分子は分子が壊れず，表面から離れすぎないように

```python
from ase.calculators.emt import EMT
from ase.constraints import FixAtoms, Hookean
from ase.optimize.minimahopping import MinimaHopping

# 拘束条件
const_Pt = [FixAtoms(indices=[atom.index for atom in Pt_211 if atom.symbol=='Pt'])]
d_HH = covalent_radii[atomic_numbers['H']] * 2
H_indices = [atom.index for atom in Pt_211 if atom.symbol=='H']
const_H2 = [Hookean(a1=H_indices[0], a2=H_indices[1], rt=d_HH*1.3, k=15.), # rtは距離の閾値[A], kはバネ係数
            Hookean(a1=H_indices[0], a2=(0., 0., 1., -(z_max+d_PtH*5)), k=5.),
            Hookean(a1=H_indices[1], a2=(0., 0., 1., -(z_max+d_PtH*5)), k=5.)]
surf.set_constraint(const_Pt + const_H2)
surf.set_calculator(EMT())
```

## Minima Hoppingを実行

Minima Hoppingを実行します．デフォルトではログはhop.logファイルに出力されます．

```python
hop = MinimaHopping(surf, Ediff0=0.5, T0=2000)
hop(totalsteps=10)
```

## 結果の可視化

`ase.optimize.minimahopping` モジュールにはMinimaHoppingの結果を可視化する `MHPlot` 関数が実装されています. matplotlibのラッパです．
黒色のチェックマークが新規に見つかった極小構造を示します．

```python
import matplotlib.pyplot as plt
from ase.optimize.minimahopping import MHPlot

plt.rcParams["font.size"] = 18 # 文字サイズを調整
MHPlot()
```

![fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629650/c2d6d3c5-fd76-12d7-3bbf-a5136a9f02c8.png)

Minima Hoppingにより見つかった極小構造も確認しておきましょう．

![fig3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629650/3eca3b59-d89e-e08f-f510-e3d9feffa0a8.png)

## 参考
- Constrained minima hopping (global optimization)
 <https://wiki.fysik.dtu.dk/ase/tutorials/minimahopping/minimahopping.html>
SpotMicroAIを作る

# はじめに

![C8A60BF5-4C54-4550-80ED-2E5AB48B3BEC.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256233/31618166-fbd8-b3bc-f402-5d4af2f407a7.jpeg)

Boston DynamicsのSpotに憧れていたら、ある日Spotを小型化したSpotMicroAIというロボットを見つけました。しかもオープンソースになっているということで、いざ作ってみることに！（[公式サイトはこちら](https://spotmicroai.readthedocs.io/en/latest/)）
ロボット制御は研究でやってましたが、電気工作の経験は皆無だったので一から勉強しながら作ってます。歩かせることを目指して日々頑張っています。

# 目次

### 準備編

1. [サーボドライバ PCA9685 を使って複数のサーボモータ MG996R を制御してみた](https://qiita.com/h_krbys/items/6a2c9f0c375ec9f3b795) 
1. [超音波センサを使ってみた]() (未)
1. [IMUを使ってみた]() (未)

### 開発編

1. [ハードウェアの準備](https://qiita.com/h_krbys/items/cb34dad936b055bf31f6)
1. [ハードウェア組み立て](https://qiita.com/h_krbys/items/4a66d7ae9da340842f36)
1. [ソフトウェア環境構築](https://qiita.com/h_krbys/items/bf0c90195031daa9f0c8)
1. [順運動学・逆運動学の実装]() (未)
1. [歩行の実装]() (未)
自機を複数のパーツで構成し換装可能にする方法を教えてください

Swiftで２Dのスクロールゲームを作ろうとしています
コードを触ること自体が全くの初心者なので
本も買いましたしログも漁ってみましたが
なかなか答を得ることが出来ません。どなたか助けてください

SpriteKitで作り始めました
自機を３つのパーツで構成し
各パーツに独自のプロパティを設定し
それぞれを換装できるような仕組みを作りたいです

Plistやenum、 UserDefaultに関するログも漁りましたが
どうしても理解が追いつきません

以下が現状書いてある部分のコードです
ring
core
wingはそれぞれ自機の構成パーツです

```ruby:GameScene.swift
import SpriteKit
import GameplayKit



class GameScene: SKScene {
    
    
    //Nodeのインスタンス化
    var wing = SKSpriteNode()
    var core = SKSpriteNode()
    var ring = SKSpriteNode()
    var title = SKSpriteNode() //タイトル
    var startBottom = SKSpriteNode() //スタートボタン
    
    override func didMove(to view: SKView) {
        
        //背景の表示
        var sizeRate: CGFloat = 0.0
        var myShipSize = CGSize(width: 0.0, height: 0.0)
        let offsetY = frame.height / 20
        let fieldImageLength: CGFloat = 1125
        for i in 0...Int(frame.size.width / fieldImageLength) + 1 {
            for j in 0...Int(frame.size.height / fieldImageLength) + 1 {
                let field = SKSpriteNode(imageNamed: "back")
                field.position = CGPoint(x: CGFloat(i) * fieldImageLength, y: CGFloat(j) * fieldImageLength)
                field.zPosition = -1
                addChild(field)
            }
        }
        
        //画像ファイルの読み込み
        
        self.wing = SKSpriteNode(imageNamed: "w1")
        self.ring = SKSpriteNode(imageNamed: "r1")
        self.core = SKSpriteNode(imageNamed: "c1")
        
        //自機を幅の1/6にするための倍率を求める
        sizeRate = (frame.width / 1.2) / self.wing.size.width
        
        //自機のサイズを計算する
        myShipSize = CGSize(width: self.wing.size.width * sizeRate, height: self.wing.size.height * sizeRate)
        
        //自機のサイズを設定する
        self.wing.scale(to: myShipSize)
        self.ring.scale(to: myShipSize)
        self.core.scale(to: myShipSize)
        
        //自機の表示位置を設定する
        self.wing.position = CGPoint(x: 0, y: (-frame.height / 2) + offsetY + myShipSize.height / 2)
        self.ring.position = wing.position
        self.core.position = wing.position
        
        //シーンに自機を表示する
        addChild(self.wing)
        addChild(self.ring)
        addChild(self.core)
       
        
        
    }
    
}
```
【powershell】正規表現でマッチした文字をハイライト表示する（ ANSI エスケープシークエンスの利用）

powershell では以前に書いた [Write-Host とループによる方法](https://qiita.com/AWtnb/items/954e32ed86f3663e777b) のほかにエスケープシークエンスでも標準出力の色を変更できるようです。

## 環境

```
Name                           Value
----                           -----
PSVersion                      5.1.18362.752
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.18362.752
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
```
## コード
```Microsoft.PowerShell_profile.ps1
function New-AnsiColorObject {
    $decimalColor = @{
        Black       = "0"
        Red         = "1"
        Green       = "2"
        Yellow      = "11"
        Blue        = "4"
        Magenta     = "5"
        Cyan        = "6"
        White       = "15"
        Gray        = "7"
        DarkRed     = "124"
        DarkGreen   = "22"
        DarkYellow  = "100"
        DarkBlue    = "17"
        DarkMagenta = "124"
        DarkCyan    = "31"
        DarkGray    = "8"
    }
    $fgTable = @{}
    $bgTable = @{}
    $decimalColor.GetEnumerator() | ForEach-Object {
        $fgTable[$_.Name] = "$([char]27)[38;5;{0}m" -f $_.Value
        $bgTable[$_.Name] = "$([char]27)[48;5;{0}m" -f $_.Value
    }
    return [PSCustomObject]@{
        FG = $fgTable
        BG = $bgTable
        RESET = "$([char]27)[0m"
    }
}
$Global:ANSI_ESC_SEQ = New-AnsiColorObject

function Write-StringHighLight {
    param (
        [string]$pattern = ".",
        [switch]$case,
        [ValidateSet("White", "Black", "Blue", "DarkBlue", "Green", "DarkGreen", "Cyan", "DarkCyan", "Red", "DarkRed", "Magenta", "DarkMagenta", "Yellow", "DarkYellow", "Gray", "DarkGray")][string]$color = "Yellow",
        [switch]$continuous
    )

    $option = ($case)? "None" : "IgnoreCase"
    foreach ($line in $input) {
        [regex]::Replace(
            $line,
            "($pattern)",
            ($Global:ANSI_ESC_SEQ.BG[$color] + $Global:ANSI_ESC_SEQ.FG.Black + '$1' + $Global:ANSI_ESC_SEQ.RESET),
            $option) | Write-Host -NoNewline:$continuous
    }
}
Set-Alias hilight Write-StringHighLight
```

かなりスッキリ書き直せました。powershell 7 以降であれば `[char]27` の代わりに `` `e `` が使えるようです（[公式ドキュメント](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_special_characters?view=powershell-7)）。
NAT＋VM環境でBigbluebuttonサーバを立ててみた(その1)

# はじめに
Zoomなどフリーでもそれなりに使えるオンライン会議システムがでているが、完全にプライベートなソリューションとしてBigbluebuttonがあるので、これを試してみた。
https://bigbluebutton.org/

家庭でやろうと思っても、

+ 専用のサーバは用意できない
+ IPアドレスが時々変わる

などの制約があるので、これをどうにかしないといけない。
サーバはVM環境(今回はvmware)を使って、WebRTCも使うので、フリーのドメインとSSL証明書の取得もやってみた。

#Ubuntu仮想マシンの準備
##1.Ubuntu16.04LTSのインストール
仮想マシンにubuntu16.04LTSをインストールする。(Bigbluebuttonは16.04を指定）
[Ubuntu 16.04 LTS 日本語 Remix](https://www.ubuntulinux.jp/News/ubuntu1604-ja-remix)が便利です。
https://www.ubuntulinux.jp/News/ubuntu1604-ja-remix

- 仮想マシンの設定
  - コア数: 4以上
  - メモリ: 8GB以上
  - ネットワーク: ブリッジ接続(自動)

※詳細は以下を参照。
http://docs.bigbluebutton.org/2.2/install.html#minimum-server-requirements

※仮想マシンの構築については、他の記事に詳細に解説があるので、そちらを参照
[Windows10上に仮想Ubuntu環境を構築（VMware Workstation Player）](https://qiita.com/iwa_gino/items/11aaffa9e49f2fc423d0)
https://qiita.com/iwa_gino/items/11aaffa9e49f2fc423d0

インストールが終わったら、アップデートを忘れずに。

```shell
sudo apt-get update
sudo apt-get dist-upgrade
```
vm-toolsは付属のものは使わず、オープンソースのものを使う。

```shell
sudo apt-get install open-vm-tools
sudo apt-get install open-vm-tools-desktop
```

##2.ネットワークの設定
ローカルのIPアドレスは固定しておく。
ここでは、ネットワークマネージャからIPv4を手動設定する。(※2020/5/4 図の差し替え）
ルータのDHCP設定を有効にしている場合は、その払い出すアドレスの範囲外で指定すると、アドレス重複のリスクもなくなる。

ネットワークマネージャから「接続を編集する」
![接続を編集する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/9e21d934-80be-2d56-7c5d-02ddd9b6dfcd.png)
![IPv4設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/61db84ad-6ec7-8932-7804-902a7cfcc4b6.png)
![IPv6設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/ca7f0fc9-7a80-0a6e-aca6-9ca27d3d080f.png)
![設定の確認](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/ca2403a5-16af-232d-9b0c-b1ce0585d735.png)

IPv6は必須ではないが、グローバルなIPv6アドレスが取得できていないときは、以下を試してみる。
/etc/sysctl.confを編集したら、ネットワークサービスを再起動する。
（上手く行かない場合は仮想マシンを再起動）

```shell:/etc/sysctl.conf
#以下の値を編集(ない場合は行追加)
# "eth0"は自分のインターフェース名(ip aコマンドで確認)に適宜修正
net.ipv6.conf.eth0.accept_dad = 0
net.ipv6.conf.default.accept_dad = 0
net.ipv6.conf.eth0.dad_transmits = 0
net.ipv6.conf.default.dad_transmits = 0
```
```shell
#sysctlへの反映
sudo sysctl -p
```

```shell
#ネットワークサービスの再起動
sudo service network-manager restart
#または
sudo ifdown --exclude=lo -a && sudo ifup --exclude=lo -a
```
##3.ルータの設定変更
外部からの接続をルータから仮想マシンへ中継する設定が必要。
自分はルータのDMZ設定を使ったが、静的NATで設定してもいい。
そのとき転送するポートは以下の通り。

+ TCP/IP ports 80/443 (for HTTP/HTTPS)
+ UDP ports in the range 16384 - 32768 (for FreeSWITCH/HTML5 RTP streams)
+ TCP/IP port 22 (for SSH 外部から接続しない場合は不要)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/5920e553-ae3e-a76c-15be-37bdc519ec58.png)


#その2へ
その2では、フリーのドメイン取得とDNSの設定を説明する。
https://qiita.com/maron2000/items/834aa44d380f0f1312ce
openapi-generator-cliを使ってみた

# はじめに

[@openapitools/openapi-generator-cli](https://www.npmjs.com/package/@openapitools/openapi-generator-cli) を試使用したメモ書き。

# OpenAPI Specificationとは

Open API Specificationとは

>
[What Is OpenAPI?](https://swagger.io/docs/specification/about/)
OpenAPIとは、RESTful APIを記述するためのフォーマットのこと。
Swagger 2.0を拡張して実装されている。

出典：https://qiita.com/teinen_qiita/items/e440ca7b1b52ec918f1b

# Open API Generatorとは

Open API Generatorとは
>
OpenAPI generatorは（中略）、OpenAPI Specificationを元にクライアントやサーバのコードを生成するソフトウェアです。

出典：https://qiita.com/amuyikam/items/e8a45daae59c68be0fc8#openapi-generator

なお、このOpen API GeneratorはOpenAPI Specificationを発行している非営利団体Open API Initiativeとは無関係に、コミュニティが開発しているツールである。

# openapi-generatorを実際にやってみた

generator はjar,npm,dockerなどの多様な形式で提供されている。
今回はnpm版を使う。

以下の2つのファイルをどっかのディレクトリに置いて、

1. [package.json](https://gist.github.com/kannkyo/7e94e8fb1775d09a4b4b5f6e980038c5#file-package-json)
2. [petstore.openapi.yml](https://gist.github.com/kannkyo/7e94e8fb1775d09a4b4b5f6e980038c5#file-petstore-openapi-yml)

以下のスクリプトを実行すると、python,java,javascriptのserver side とclient sideのコードが生成される。

```shell
yarn install
# generate server side code
mkdir server
yarn gen:python-flask
yarn gen:spring
yarn gen:nodejs-express-server
# generate client side code
mkdir client
yarn gen:python
yarn gen:java
yarn gen:javascript
```

ちなみに、このgeneratorの注意点は [60種類以上のgenerator](https://openapi-generator.tech/docs/generators) が提供されているにもかかわらず、OpenAPI Specificationを完全にサポートした言語はないことだ。といっても、非対応なものは [Custom DataType, MultiServerなど](https://openapi-generator.tech/docs/generators/spring/#feature-set) のレア？なものに限られるようだが。・・・多分、大丈夫。

# swagger-codegenは

これとは別にSmartBear社が商用で開発している[swagger-codegen](https://github.com/swagger-api/swagger-codegen)というツールもある。

これも使っては見たが…。正直不具合が多すぎてどうしようもない。まずpythonもjavaもそもそも実行すらできず。javaはpom.xml間違ってるし、Pythonはimport足りてないし。

swagger-codegenは、現時点(2020/5/2)でissueが2265件あって、[直近1ヶ月間でcloseできたissue](https://github.com/swagger-api/swagger-codegen/pulse/monthly) の件数は17件、新たに増えたissueが40件。もうダメやん。

つかうならopenapi-generator一択かな。
円周率に近い分数が欲しい


# 円周率に近い分数とは

$\frac{355}{113}$ はなかなか円周率に近い。

```math
\begin{array}
\hbox{}\pi &=& 3.14159265\ldots \\
\frac{355}{113} &=& 3.14159292\ldots \\
\end{array}
```

なので，なんと 7 桁も一致している。

## 覚え方

本題に関係ないが，覚え方を書いておく。

[1] 奇数を順に三つ書く：`135`
[2] それぞれダブルにする：`113355`
[3] ど真ん中に「分の」を入れる：`113 分の 355`

いや，こんなもん覚えて何の役に立つの？
まあ，あれだ，手元にパソコンは無いけど電卓（関数電卓じゃないやつ）はあって，円周率を含む 4 桁以上の精度の計算がしたいときだな。
半世紀生きてきて，そういう機会は無かったけどな。仮にあったとしても円周率は 50 桁くらい覚えてるしな。

# 任意の精度で

では，もう少し精度を高めたいとき，分子・分母をどうやって求めればいいのだろうか。
あるいは，精度はもっと低くてよいから，もっと簡単な分数で表したいとしたら？

Ruby には Float オブジェクトを，与えられた許容誤差のもとに**なるべく簡単な分数**の Rational オブジェクトに変換する [Float#rationalize](https://docs.ruby-lang.org/ja/2.7.0/method/Float/i/rationalize.html) というメソッドがある。素晴らしい！

また，円周率は [Math::PI](https://docs.ruby-lang.org/ja/2.7.0/method/Math/c/PI.html) という定数として定義されている。

この二つの道具立てを使うと，例えば，許容誤差 0.1 の範囲でなら，

```rb
p Math::PI.rationalize(0.1) # => (16/5)
```

のようにして得られる。
$\frac{16}{5}$ は 3.2 だから，円周率より 0.058 くらい大きな値だ。確かに許容誤差に収まっている。

許容誤差 0.00000001 なら

```rb
p Math::PI.rationalize(0.00000001) # => (100798/32085)
```

となる。これだと 8 桁一致する。

ただし，注意しなければならないのは，Math::PI は真の円周率ではない，ということ。
あくまで Float オブジェクトとして表せる**円周率の近似値**に過ぎない。
だから

```rb
Math::PI.rationalize(0.000000000000000001)
```

みたいなことをしても意味が無い[^fe]。

[^fe]: Ruby の Float が持ちうる精度はシステムによって違うが，たいがいの場合，10 進数にして 15 桁くらいだそう。

# 許容誤差を与えないとどうなる

ここからは本記事の主題から外れる。せっかく `Float#rationalize` が出てきたので，これについてもう少し見ておこう，ということだ。

このメソッドは引数（許容誤差）を与えない使い方もできる。
さきほど示したリンク先の公式リファレンスの説明はやや不正確だが，`Float#rationalize` に引数を与えない場合，その Float が持ちうる精度くらいの許容誤差を与えたのと同じになるらしい。

Float で表せる数は，数直線上に均一に分布してはいない。絶対値が 0 に近いところでは非常に密に分布しているが，絶対値が大きいところではスカスカになっている[^suka]。
これは浮動小数点数の仕組みを知っていれば容易に理解できることだ[^float]。

[^suka]: そして，絶対値の極めて大きなところには，表せる数が一つもない。

[^float]: しかし，浮動小数点数の仕組みを説明することはこの記事ではしない。


言い換えれば，ある浮動小数点数とその両隣の浮動小数点数との間隔は場所によって違っている，というわけだ。

引数を与えない `rationalize` は，`self` とその**隣**との間隔くらいの許容誤差のもとに Rational オブジェクトを作ってくれる。
いや，隣との間隔の半分か？　うーん，そうでもないようだな。
正確なところは私にも分からないが，だいたいそのくらいの許容誤差であるようだ。

## `0.1.rationalize` は厳密に 0.1

浮動小数点数についてある程度理解している人なら，Ruby の浮動小数点数リテラル `0.1` が数学的な 0.1 とはわずかに違う数を表していることを知っていると思う。

Ruby の浮動小数点数はふつう基数が 2 である，言い換えれば有効数字の部分が 2 進数で表される。
数学的な 0.1 は 2 進数では無限小数になってしまい，これを有限桁で切ると誤差が出てしまう，ということだ。

ところが

```rb
p 0.1.rationalize # => (1/10)
```

となる。
Ruby の `0.1` から見た数学的な 0.1 は，`0.1` の隣の浮動小数点数よりも近いところにある。だから引数無しの `rationalize` で変換すると，1/10 にあたる Rational オブジェクトが得られる，ということのようだ（よく分かんないけど）。


# `Float#to_r` とは違うのか？

実は Float を Rational に変換するメソッドとしては，`rationalize` のほかに [Float#to_r](https://docs.ruby-lang.org/ja/2.7.0/method/Float/i/to_r.html) というものもある。

これは違うものなのか？　違う。

実は浮動小数点数は（`Float::INFINITY` や `Float::NAN` といったものを除き）すべて数学的には有理数（整数分の整数で表せる数）である。

`Float#to_r` は自身が表している有理数に対応する Rational オブジェクトを返す。
したがって，浮動小数点数とそれを `to_r` したものとは，数学的に厳密に等しい。

では Ruby の `0.1` はどんな有理数なのか。

```rb
p 0.1.to_r # => => (3602879701896397/36028797018963968)
```

分子分母の数字列を比べれば分かるように，分子の 10 倍と分母とは非常に近い。前者のほうが 2 だけ大きいので，Ruby の `0.1` は数学的な 0.1 よりもごくわずかに大きい数値であることが分かる[^sy]。

[^sy]: これももちろん，システムによって異なる。が，おそらくわりと多くの環境でこれと同じ結果になるのじゃないかな。

# おわりに

実はこの記事は円周率の有理数近似について書きたかったのではなく，わりと最近知った `Float#to_r` や `Float#rationalize` が面白く思えたので，紹介しようと思って書いた。
5 月 LeetCode 挑戰, W1D3, Ransom Note, in Swift

資料結構及演算法： `Hash Table` `String`

- 挑戰頁面 - [Ransom Note](https://leetcode.com/explore/challenge/card/may-leetcoding-challenge/534/week-1-may-1st-may-7th/3318/)
- 原題目- [383. Ransom Note](https://leetcode.com/problems/ransom-note/)

## 解題想法

這題直覺上也是 hash table 問題。

基本步驟如下：

1. 把 ransom note 中有哪些字元，各出現過幾次記錄下來
2. 走訪 magazine 的每一個字元有出現就把計數減一

### 資料結構的使用

和昨天的題目 ([Jewels and Stones](https://qiita.com/vc7/items/395c629ac3d1a0fc18cf)) 不一樣的地方是，前一天題目有提到 jewels(`J`) 裡面的值可以保證獨一無二 (distinct) ，因此由這個限制來看，解題的時候就可以用 set 。

但是今天從題目來看無論是 ransomNote 還是 magazine ，其中的字元都有可能會重複出現，因此應該要用 dictionary 而不能用 set 。

## 程式碼

``` swift
class Solution {
    func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool {
        // 提早排除
        if ransomNote.count > magazine.count { return false }

        var hashTable = [Character: Int]()

        // 計數
        for character in ransomNote {
            hashTable[character] = (hashTable[character] ?? 0) + 1
        }

        // 比對
        for character in magazine {
            if let count = hashTable[character] {
                hashTable[character] = (count - 1 == 0) ? nil : count - 1
                if hashTable.isEmpty { return true }
            }
        }

        return hashTable.isEmpty
    }
}
```

## 複雜度分析

r 為 ransomNote, m 為 magazine。

- 時間複雜度： O(m.length)
  - 如果 ransomNote 的長度大於 magazine 的長度就代表以 magazine 的內容無法構成。有了這個條件判斷並排除明顯無法達成要求的測試案例，時間複雜度就能夠從 O(r.length + m.length) 簡化到 O(m.length) 。
- 空間複雜度： O(r.length)
  - 用在紀錄 ransomNote 的 hash table

## 執行結果

``` text
Runtime: 32 ms (beats 98.48%)
Memory Usage: 21.3 MB
```

### 觀察

提前排除的那個判斷無論有沒有加並沒有讓 runtime 有改變。其中也有可能是因為測試案例並沒有讓這個判斷能有顯著表現。
GNU/Linuxにkindを使ってkubernetesをセットアップする


GNU/LinuxでDockerがセットアップされている環境に、kindをつかってkuberenetesクラスタをセットアップします。

## kubectlのインストール

[公式解説](https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/)
 
```bash

$ curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl
$ sudo install -m 755 -o root -g root ./kubectl /usr/local/bin
$ source <(kubectl completion bash) # bash補完設定
```

## kindのインストール 
[公式解説](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)

```bash

$ curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.8.0/kind-$(uname)-amd64
$ sudo install -m 755 -o root -g root ./kind /usr/local/bin
$ source <(kind completion bash) # bash補完設定
```

## k8s クラスタの作成

### 最新のk8sクラスタをセットアップする場合

[公式解説](https://kind.sigs.k8s.io/docs/user/quick-start/#creating-a-cluster)

```bash
$ kind create cluster --name k8s-test
$ kubectl cluster-info --context kind-k8s-test
$ kubectl get node
NAME                    STATUS   ROLES    AGE     VERSION
k8s-test-control-plane  Ready    master   2m12s   v1.18.2
```
※kindは複数のクラスタを作成し、[切り替えての利用](https://kind.sigs.k8s.io/docs/user/quick-start/#interacting-with-your-cluster)が可能です。

### 作成するk8sのバージョンをkindで指定する場合

kindのReleaseページを参照し、control-planeとworkerのimageを以下のyamlファイルの例のように指定します。ここではv1.14系を指定し、`k8s-1.14.yaml`というファイル名で保存します。([参考](https://kind.sigs.k8s.io/docs/user/quick-start/#setting-kubernetes-version))

```yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  image: kindest/node:v1.14.10@sha256:6cd43ff41ae9f02bb46c8f455d5323819aec858b99534a290517ebc181b443c6
- role: worker
  image: kindest/node:v1.14.10@sha256:6cd43ff41ae9f02bb46c8f455d5323819aec858b99534a290517ebc181b443c6
```

作成したyamlファイルを指定して、kindでクラスタを作成します。

``` bash
$ kind create cluster --config k8s-1.14.yaml 
$ kubectl cluster-info --context kind-kind
$ kubectl get nodes 
NAME                 STATUS   ROLES    AGE    VERSION
kind-control-plane   Ready    master   2m9s   v1.14.10
kind-worker          Ready    <none>   87s    v1.14.10
```
iphoneカメラの自撮りとコラボ動画の作成に関して。（１）

今更ですが先ずはiPhoneの最初の画面にカメラマークをクリックしてカメラを自分側に向ける、カメラ切り替えボタンで自分を撮影できます。以下のマークを押すと自分の顔が映し出されます。iPhoneのバージョンによって下記のように違います。
![img20131218130128053385.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/74663e44-354f-10be-c1a1-1e50bbef137a.jpeg)
最近のバージョンは右下です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/25353f68-fe9e-40e6-a746-cba32d5169e1.jpeg" width="70%">
これでカメラの設定ができたら、写真の左隣のビデオに切り替え丸いボタンを押せば動画撮影開始です。
撮影中赤くなったボタンを押せば終了になります。楽器等の自撮りはスタンドがあると良いですが、両面テープ等で壁に貼り付けるのも案です。
では先ず自撮りしてみましょう。
プロジェクト内のデュレーションとフレームレート を指定してまとめて変更

#概要
Adobe ExtendScriptを利用してプロジェクト内のデュレーションとフレームレート を指定してまとめて変更します。

#作例
![GUI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299114/0b2d1c7a-7887-1089-37f6-beab76834e66.png)

#解説

```
var durationtext=this.add("statictext", [20, 0, 120, 10],"デュレーション")
var durationedittext = this.add("edittext",[20, 15, 120, 45], []);
var fpstext=this.add("statictext", [20, 50, 120, 60],"フレームレート")
var fpsedittext= this.add("edittext",[20, 65, 120, 95], []);
var btn = this.add("button",[20, 100, 120, 120], "実行");
var i;

btn.onClick = function(){
//ボタンが押されたら入力された数字(文字列)を 数値に変換
var fps =Number(fpsedittext.text);
var duration =Number (durationedittext.text);

//プロジェクト内のアイテムをapp.project.items[i]に格納する
for(i =1; i<= app.project.items.length; i++){
    app.project.items[i];
    
//app.project.items[i]からinstanceofを使ってCompItemかを判定する
//CompItemか判定した後app.project.items[i]にフレームレートとデュレーションを設定する
    if((app.project.items[i] instanceof CompItem)) {
        app.project.items[i].duration = duration;
        app.project.items[i].frameRate = fps;
    } 
}
//結果をアラート表示
alert(i+'つのコンポとアイテムのデュレーションとフレームレートを設定しました');
}

```

どのような動きをするかはコメントを読めば分かると思います

Aeで制作するループ素材のディレーションを変更するのに便利です
関連記事
[[ループ素材作成]AfterEffectsで髪の毛をエクスプレッションで揺らす方法](https://qiita.com/hi_tyanww/items/04f89b566f7fa491d6e6)

参考資料
After Effectsスクリプトリファレンス様
[例文01](http://aejsx.hiroshisaito.net/home/after-effects-scripting-examples/example1_invaildframerate)
参考書籍
After Effects自動化サンプルプログラム　上
After Effects自動化サンプルプログラム　下
Adobe JavaScriptリファレンス
ExtendScript Toolkit（ESTK）基本編
gmail に届いたメールを1日1回Discordに送る

毎日深夜に昨日届いたメールを全部Discordに転送する

# 1. Discord のウェブフックを作成する

![step1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/f4ed6da3-b147-f712-ac95-d3692f98e02b.jpeg)
![step2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/85c3695d-b0c0-4a3b-53ec-359bd788e874.jpeg)
![step3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/b24b4657-398f-4be8-2f37-31b160678bbd.jpeg)
![step4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/a10dd503-cfbc-f55e-3a52-673653fe5a36.jpeg)

# 2. Google App Scripts のプロジェクトを作成する

https://script.google.com/home
にアクセスします

![step5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/5939460b-1244-20d8-3864-7f977b5b7893.jpeg)

以下のスクリプトを入力します

```js
function main() {
  const yesterdaysEmails = getYesterdaysEmails(EMAIL_FROM); // Discordに転送したいメールの送り元アドレス
  const webhook_url = DISCORD_WEBHOOK_URL; // DiscordのウェブフックURL
  yesterdaysEmails.forEach(email => {
    sendToDiscord(webhook_url, email.getPlainBody());
  });
}

function getYesterdaysEmails(from){
  const today = new Date();
  const yesterday = new Date();
  yesterday.setDate(today.getDate() - 1);

  const threads = GmailApp.search(`from:${from} after:${yesterday.getFullYear()}/${yesterday.getMonth() + 1}/${yesterday.getDate()} before:${today.getFullYear()}/${today.getMonth() + 1}/${today.getDate()}`);
  const msgs = GmailApp.getMessagesForThreads(threads);
  
  const ret = [];
  for(let i = 0; i < msgs.length; i++) {
    for(let j = 0; j < msgs[i].length; j++) {
      ret.push(msgs[i][j]);
    }
  }
  return ret;
}

function sendToDiscord(webhook_url, text) {
  const data = {
    content: text,
  };
  const res = UrlFetchApp.fetch(webhook_url, {
    method: "post",
    headers: { 'Content-Type': 'application/json' },
    payload: JSON.stringify(data),
  });
}
```

![step6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/2657d6a5-dbd2-9733-e477-09d8b1c9b128.jpeg)

# 3. 実行テストする

![step7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/80fbca52-e1ed-687b-fd48-99a7d9109530.jpeg)

実行テストして**昨日の分**のメールがDiscordに投稿されればOK


# 4. 1日1回実行するトリガーをセットする

![スクリーンショット 2020-05-03 21.34.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/bca2a71a-6e69-1c2b-6239-14a7322086a0.png)

![スクリーンショット 2020-05-03 21.35.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/7c6494aa-970e-51dd-17ad-3e54d783bb87.png)

![スクリーンショット 2020-05-03 21.36.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101688/7a1ebcfd-039f-31d3-ed05-557eb6b0d01d.png)

おわり
RAPIDSの学習のためのまとめ

# RAPIDSとは？
pandasの処理のGPU化などにより、機械学習の前処理などの高速化を図るためのパッケージ

APIの種類
cuDF, cuML, cuSPATIAL, cuGRAPH, cuSIGNAL, cuXFILTER, CLX, NVSTRINGS

## 概要
https://docs.rapids.ai/overview/RAPIDS%200.13%20Release%20Deck.pdf

## 何ができるか（使用例）
https://medium.com/rapids-ai

## ドキュメント
https://docs.rapids.ai/api

## ノートブック・サンプル
### cuDF and Dask-cuDF
https://rapidsai.github.io/projects/cudf/en/0.13.0/10min.html
### RAPIDS Notebooks
https://github.com/rapidsai/notebooks
### RAPIDS Notebooks 2
https://github.com/rapidsai/notebooks-contrib
AzureのAppServiceのRubyイメージではtiny_tdsを利用できない

## 概要
タイトルの通りですが、AzureのAppserviceで使えるRubyのデフォルトイメージだとfreeTDSのバージョンが古いため、
tiny_tdsを使ってSQLServerへの接続ができませんでした。

## 対処法
Appserviceコンソールなどからは対処不可、自前のコンテナイメージ使いましょう。
なお、RubyのデフォルトイメージのgithubにPRあがってるみたいだがまだ未処理
これがマージされれば使えるかな？
https://github.com/Azure-App-Service/ruby/pull/38

以下、いろいろ検証してみたこと。

## AppServiceのコンテナをローカルで使ってみる
いろいろ調べるとdockerイメージが公開されている。
https://github.com/Azure-App-Service/ruby
（DockerHubにもある）

これを使って色々と。

こちらにローカルで使う方法がありましたので、それを実行。
https://github.com/Azure-App-Service/teamblog/blob/master/docs/Images.md

``` shell
docker pull appsvc/<ImageTag>

docker run \
    -d -it -P \
    --volume $(pwd):/home/site/wwwroot \
    --env PORT=8080 \
    --publish 8080:8080 \
    appsvc/<ImageTag> 

curl localhost:8080

docker exec -it <container> bash
```

これでひとまずは動く。(別にrailsのアプリの場所でなくても大丈夫そう)
で、`localhost:8080`を叩くと、AppServiceのおなじみの画面が出る。

![Bad Request]()

ここからbashでコンテナに入ってみて、いろいろ確認。

```
$ apt show freetds-bin
Package: freetds-bin
Source: freetds (0.91-6)
Version: 0.91-6+b1
Installed-Size: 750 kB
Maintainer: Steve Langasek <vorlon@debian.org>
Depends: libc6 (>= 2.17), libgnutls-deb0-28 (>= 3.2.10-0),
libgssapi-krb5-2 (>= 1.10+dfsg~), libodbc1 (>= 2.3.1), libreadline6 (>= 6.0), libsybdb5 (>= 0.82),
libtinfo5, freetds-common
Homepage: http://www.freetds.org/
Tag: interface::commandline, role::program
Section: database
Priority: optional
Download-Size: 217 kB
APT-Manual-Installed: yes
APT-Sources: http://deb.debian.org/debian/ jessie/main amd64 Packages
Description: FreeTDS command-line utilities
```

(freetds-devも同じような感じ。)
ということで、0.91のfreetdsが入ってる。しかし、直近のtiny_tdsでは`Do you have FreeTDS 0.95.80 or higher installed?`
とか言われる。
tiny_tdsのバージョンを落とせば入るかもしれないが、0.91に対応してるバージョンを見つけるのが大変なのでここで打ち切り。

ちなみにbashで入ったとき、gemとかはここにある。
`/usr/local/.rbenv/versions/2.6.2/bin` (Rubyのバージョンは置き換えて)


## 最後に
早くマージしてほしい。
[Kotlin]Firebase InAppMessagingの実装

# はじめに
 - 実装なしで画面表示時にダイアログを出せます

# 画面
ダイアログが出た際の表示

<img width="375" alt="File.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199764/2b102116-67f1-0dd4-430e-e5f9efdaac7e.png">


# 実装
applicationレベルのgradle

```build.gradle(app)

dependencies {
   〜

    // core
    implementation "com.google.firebase:firebase-core:17.4.0"
    // InAppMessaging
    implementation 'com.google.firebase:firebase-inappmessaging-display:19.0.6'
}
```

Activityの実装なし

# おわりに
別アプリでは問題なく、初回インストール直後の起動で問題無く表示されましたが、
今回のサンプルではなぜかインストールして直後では表示されず、
インストール→アプリキャッシュクリア→再度アプリ表示にてダイアログが表示されました。
原因わかる方ご指摘い頂けますと幸いです。

ソースコードは[こちら](https://github.com/yoshihitoijichi/FireabseSample)
Windows .rc ファイルが UTF-16(LE)だと, git + cmake + MinGW で扱いずらいメモ

## 背景

Windows の `.rc` ファイル(resource file)は, Visual Studio などで生成すると UTF-16(LE. BOM 付き) がデフォルトであり, 推奨の模様.

MinGW で Windows バイナリをコンパイルできるようにしたい.

## 問題

MinGW windres は, UTF-16 ファイルには対応していない. UTF-8? と想定してパースしてしまう.


`.gitattributes` で `.rc` に utf-16 le エンコーディングを指定している場合, `.rc` を UTF-8 などに変換して commit しようとしようにも,  convert できないエラーがでる.

### llvm-mingw

llvm-mingw(clang コンパイラ)では, UTF-16 ファイルを読み込むことができない.

CMake でプロジェクト管理している場合, set_source_files_properties(myfile.rc PROPERTIES LANGUAGE RC) などとして resource ファイルであることを明示する必要がある.

### llvm-rc

llvm-rc も同様に UTF-16 をサポートしていない(UTF-8 も?)

https://reviews.llvm.org/D38432

パッチが出ているがマージされていない(as of LLVM 10.0.0)

## 解決方法

`.rc` の量が多くなければ, MinGW 用に別 `.rc` ファイルを用意(UTF-8 or ASCII(cp932?))するのがよいと思われる. このとき, `.gitattributes` でエンコーディング強制指定の問題を回避するため, 拡張子を変えておくのがよいでしょう.
numpyでヒストグラムの最大地点を取得する関数

meanでもmedianでもなくhmaxを取得したい時がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278468/4b973719-5eff-8f89-1856-b63361eb3cac.png)

関数

```py
def hmax(x, bins=20):
    import numpy as np
    hist, bins = np.histogram(x, density=True, bins=20)
    delta = (bins[1]-bins[0])/2
    xr = np.linspace(np.min(bins)+delta,np.max(bins)-delta,len(bins)-1)
    return xr[np.argmax(hist)]
```

プロット

```py
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
%matplotlib inline
plt.rcParams['font.size']=15

x = np.random.beta(2,5,100000)
df_plot = pd.DataFrame(fit.extract()['mu'])
c = sns.color_palette('husl',3)
sns.distplot(x,color='gray')
plt.axvline(x=np.mean(x),label='mean',color=c[0])
plt.axvline(x=np.median(x),label='median',color=c[1])
plt.axvline(hmax(x),label='hmax',color=c[2])
plt.legend()
plt.show()
```
【初心者向け】10行以内のスクリプト(5.pandasを使用した時系列データのresample)

### 【初心者向け】10行以内のスクリプト(5.pandasを使用した時系列データのresample)
pythonで色々なライブラリを使えば、「少ないコードでもちょっとした事が出来て、少なければ5行程でもちょっとしたスクリプトが作れ、便利だな。」と思ったので、pythonやその他、コマンドを羅列しただけのものも出てくるかも知れませんが、10行程のスクリプトを不定期で投稿してみようと思います。

**第5回**として、<font color=blue>pandasを使用した時系列データのresampleを投稿したいと思います。</font>

売上や金融商品の相場、その他、様々な時系列データを月次や四半期毎で、集計したい場面は多いと思います。
pandasのresampleを使えば出来るという事を知り、私自身が忘れないうちに、為替相場のデータを例に年次と四半期で集計する事例を投稿したいと思います。

***

【環境】
Linux: debian10
python: 3.7.3
pandas: 1.0.3
jupyterlab: 2.1.0

データは、fredの為替相場のデータを使用したいと思います。

### 

以下の様なデータがあったとして

DATEDEXJ,PUS
2015-01-01,NaN
2015-01-02,120.20
2015-01-05,119.64

**平均でリサンプルする構文**
<font color=blue>データフレーム.resample(rule='頻度コード').mean()</font>
・頻度コード: 年次('Y')、四半期('Q')、月次('M')、週次('W')
・例として、「df_dexjpus」というデータフレームの年次の平均を「df_year」というデータフレームに格納する場合
df_year = df_dexjpus.resample(rule='Y').mean()


#### 1. pandasで、為替データを年次・四半期の平均でresampleするスクリプト

コードは、jupyterで実行しました。

```python:python3.7
# 為替相場のリサンプル(年次・四半期・月次・週次)
# 為替相場のデータフレーム(df_dexjpus)
# infile = ('./dexjpus_20200417.csv')
import pandas as pd
import matplotlib.pyplot as plt

df_dexjpus = pd.read_csv('./dexjpus_20200417.csv' ,index_col='DATE' ,parse_dates=['DATE'])

# 年次
df_year = df_dexjpus.resample(rule='Y').mean()

# 2017年のデータ
df_2017 = df_dexjpus.loc['2017-01-01' : '2017-12-31']

# 2017年の四半期の為替の平均
df_quarter = df_2017.resample(rule='Q').mean()    
 
```
### 2. スクリプトについて、順番に見ていきたいと思います。

**2-1.ライブラリのインポート、データの読む込み**

```python:python3.7

# 為替相場のリサンプル(年次・四半期・月次・週次)
# 為替相場のデータフレーム(df_dexjpus)
# infile = ('./dexjpus_20200417.csv')
import pandas as pd
import matplotlib.pyplot as plt

df_dexjpus = pd.read_csv('./dexjpus_20200417.csv' ,index_col='DATE' ,parse_dates=['DATE'])

df_dexjpus


	DEXJPUS
DATE 	
2015-01-01 	NaN
2015-01-02 	120.20
2015-01-05 	119.64
2015-01-06 	118.26
2015-01-07 	119.5

```

**2-2. 1年毎で、見てみようと思います。**

```python:python3.7

# 年次
df_year = df_dexjpus.resample(rule='Y').mean()

df_year

	DEXJPUS
DATE 	
2015-12-31 	121.049084
2016-12-31 	108.656932
2017-12-31 	112.098554
2018-12-31 	110.397390
2019-12-31 	109.018835
2020-12-31 	108.775333

```

**2-3. 例として、2017年を見てみようと思います。**

```python:python3.7

# 2017年のデータ
df_2017 = df_dexjpus.loc['2017-01-01' : '2017-12-31']

 	DEXJPUS
DATE 	
2017-01-31 	114.872105
2017-02-28 	112.911579
2017-03-31 	112.916522
2017-04-30 	110.091000
2017-05-31 	112.243636
2017-06-30 	110.914091
2017-07-31 	112.417000
2017-08-31 	109.826957
2017-09-30 	110.776000
2017-10-31 	112.914762
2017-11-30 	112.819000
2017-12-31 	112.940500

```

**2-4. 最後、2017年四半期毎のデータを見てみたいと思います。**

```python:python3.7

# 2017年の四半期の為替の平均
df_quarter = df_2017.resample(rule='Q').mean()

df_quarter

 	DEXJPUS
DATE 	
2017-03-31 	113.524098
2017-06-30 	111.113906
2017-09-30 	110.950476
2017-12-31 	112.891803

```

**以上、5.pandasを使用した時系列データのresampleでした。**
RubyからGo（ジャンル:勉強日記vol.1）

## 近況報告
　テックキャンプを卒業し，ついに就職活動です。前の記事で述べた通り，
　　・個人アプリの修正及び機能付与
　　・カリキュラムのドリル
　　・新しいことへのチャレンジ（dockerとGo言語）
　　・就職活動
を軸に勉強を進めています。個人アプリの大まかな修正は順調に進んでいます。ドリルに関しては，先輩曰く，スクールの料金の半分の価値があるとのことなので，進めています。正規表現など穴がわかるので助かります。dockerは意義を理解してインストールし，起動まで進みました。環境構築はまだ解読が進んでいません。Golangは後述。就活は今週面接があるのですが，ラフな気持ちで行こうと思います。

# 今回のお話
　Golangの勉強を始めた経緯
　いまなにしてる
　気づきメモ（rubyでは出会わなかった話メイン）
## Golangの勉強を始めた経緯
### 勢いのある言語のため
　golangは２００９年にオープンソースとして発表された言語であり，機能性，高速という面で脚光を浴びた言語です。最近のエンジニアが学びたい言語としても上位に位置し，近年はアプリケーションの一部をGoに変えることで処理速度をあげる試みなどされているみたいですね。人気に比例しGolangの需要は年々増加しているもののGolangを扱えるエンジニアが少ないことから言語ごとの給料でも上位に位置するとか（あくまでも企業が求めているのはGolangを実践レベルで使える人だが）。
### 学習コストが低いため
　某雑食系Youtuberもいうように学習コストが低いとされています。従来あった継承などの要素を削ぎ落とし，シンプルさを求めた結果生じた言語であるため，学習量はCやPythonなどと比べて少ないと考えています。また，私はRubyをある程度扱っていたので，類似点を探しつつ勉強できるのでかなり手をつけやすいと考えています。別の言語を知ることで，今よりもっと広いみかたでコーディングできることも期待しています。
### 活用範囲
　Go単品でアプリケーションを作成することは可能です。ただアプリケーションの一部をGolangに変えて運用するというのがメルカリとかのように増えているらしく，もともとGolangを使っていなかったが起動性，高速処理の利点から用いるようになる企業が他の言語より多いと考えました。ポートフォリオに関してもrubyでメインを組み立てて一部をGoにしてアピールできるのでアリだなと考えました。
　たしかにPythonも興味はあるのですが，同じような言語としてRubyを選択している以上用途が被っていては二兎追うものは一兎を得ずになりかねないので，就職して必要になった時に覚えようと思います。

**あくまでもサブの領域の言語であり，メインはRubyまたは企業で用いる言語というスタンスは変わりません。**

## いまなにしてる
・Goのインストール(公式より)
・vsコードでGoを扱えるように準備
・公式のガイドをみてHello,Worldを出力

## 気づきメモ

### hello world

```test.go
package main

import "fmt"

func main() {
    fmt.Println("hello, world!")
}
```
Go言語はシンプルな構文と厳格なルールで成り立っており，ルールを破ると実行を行ってくれません（エラー箇所はしっかり示してくれます）。
[packageについておおよその理解](https://qiita.com/pei0804/items/5f28b42d01fcadb3f765)

printlnはI（アイ）ではなくL（エル）
print Line の略

### 数値型
Golangでシンプルな文法による駆動を可能としているのは厳格なルールがあるからです。変数の定義には予め変数の型を宣言しなければいけません。その中でも数値型はRubyになかった表現があって厄介でした。

**ビット，浮動小数点，符号あり整数**

なにそれ。。。本当は止まらずテキストを駆け抜けたいのですが，根本の要素なので止まります！
簡単に整理します。

●浮動小数点 (ex)var i float = .0001e+4
少数の表示方法。0.001なら，1.0*10*-3(10の−３乗)。なんか高校で見たことある表現w
●符号あり（なし）整数　
-とか＋とかの概念がない数列。２進数は０，１，１０，１１，，，のように符号を必要としない。
●ビット　unit8 unit16
そもそもパソコンは０と１（onとoff）の区別の集合によって動いている。その組み合わせ１つで１ビット
unit8なら単体８ビット，つまり，符号なし二進数８桁
unit16なら符号なし二進数１６桁
桁数が多い方が多くの数字を操れる。

追記　関数遅延 9/5/2020

```test.go
~省略~
func main {
　　　　処理A
　　　　処理B
　　　　defer　関数C
　　　　処理D
~省略~
```
このような処理があったとして，deferで指定された処理は全体の処理が終わった後に行われる。

❌上から処理して終わった後に処理が行われる
⭕️全ての処理が終了した時に最後に実行される
⇨defer定義なし，処理Bでエラーが生じたとして処理Dにファイルを閉じる処理があったとしたら，エラー後，処理が行われてファイルが開いたままプログラミングが終了してしまう（実行前の状態に戻らない）。deferでファイルを閉じる処理を定義しておけば，エラーが生じても閉じる処理をしてくれる。




随時更新していきます