OmniAICreator/Qiita-1.07M huggingface dataset:
【rails】 path url ・・・違いは？

#結論 
##path
* `link_to`でよく使われる
* `redirect_to`以外で使用する

## url
* `redirect_to`の時に使用する

##ちなみにpathの場合
`<%= link_to '店舗様専用登録ページ', 'signup' %> `
みたいにシングルクォーテーションで囲ってもいけますし、
`<%= link_to '店舗様専用登録ページ', signup_path %>`
こう書いても大丈夫でした。

# 最後に
間違っているところがあればご指摘いただけると幸いです。

# 参考記事
https://railsguides.jp/routing.html

# 追記 11/24
ご指摘いただいた箇所があったので訂正致します。
`<%= link_to '店舗様専用登録ページ', 'signup' %> `
文字列として渡してもいいと書いてしまいましたが、URLを変更したくなった時に変更する箇所が多くなってしまったり、設定によってリンクが機能しなくなることからRailsではあまり推奨されていないみたいです。
ヤフービジネスにSelenium Pythonでログインする　

ヤフービジネスのIDとパスワード数百件。
はたしてこのエクセルリストのIDとパスワードでログインできるのでしょうか。
パスワードを変更してもエクセルのリストが更新されないこと多数。
そこで、スクレイピングでログイン確認をします。

簡単かと思いきや少しはまったのでメモします。

結論
#直接ログイン画面からログインしない。ヤフー内の別のページからログイン画面に遷移してログインする。

例えば
直接ログイン画面に遷移せず
https://business.yahoo.co.jp/
↓
https://login.bizmanager.yahoo.co.jp/login
の順番で遷移します。

ヤフービジネスログイン画面のソースをみてみると多数のhidden項目があります。
この.crumbが空だとログインできない(何もおこらない）仕組みになっているようです。
なのでhiddenの.crubが空の状態で正しいIDとパスワードを入力しても、何もおこらないし、間違ったIDとパスワードを入力しても「IDとパスワードが違います」の画面すら表示されないのです。


```:ヤフービジネスログイン画面　hiddenの.crumbに値なし
<form method="post" action="/login.php" autocomplete="off" name="login_form" onsubmit="return checkMultipleSubmit();">
<input type="hidden" name="url" value="https://business.yahoo.co.jp/" data-rapid_p="1">
<input type="hidden" name="action" value="login" data-rapid_p="2">
<input type="hidden" name=".flow" value="" data-rapid_p="3">
<input type="hidden" name=".crumb" value="" data-rapid_p="4">

```

https://business.yahoo.co.jp/
↓
https://login.bizmanager.yahoo.co.jp/login
の順番で遷移すると
hiddenの.crubに値が入力されています。

```:ヤフービジネスhiddden.crumbにセッションの値が設定された後
<form method="post" action="/login.php" autocomplete="off" name="login_form" onsubmit="return checkMultipleSubmit();">
<input type="hidden" name="url" value="https://business.yahoo.co.jp/" data-rapid_p="1">
<input type="hidden" name="action" value="login" data-rapid_p="2">
<input type="hidden" name=".flow" value="" data-rapid_p="3">
<input type="hidden" name=".crumb" value="dD14Q0R0ZkImc2s9eGlqMXh3dTRLcVJzM29KQ3pLMlIwaHNVcVZvLQ==" data-rapid_p="4">

```

この状態になった後にログインすればスクレイピングでログインできるようになります。

環境
Windows10
Python3.8.3
Selenium
グーグルクローム

・driverにクロームドライバーが設定されているものとします。
・あまりにも早く進むとブロックされてしまうかもしれないのであえてtime.sleepを入れています。


```ヤフービジネスログインpythonselenium
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

#直接ログイン画面に進まない
driver.get("https://business.yahoo.co.jp/")
driver.get("https://login.bizmanager.yahoo.co.jp/login.php")    

#確実にsendkeyするために関数を作成しました。
move_textbox_id(driver,"user_name","ここにID")        
move_textbox_id(driver,"password","ここにパスワード")      
        
#早く進みすぎてブロックされるといやなのでゆっくりと進みます。
time.sleep(1)     
    
element = driver.find_element_by_xpath("//*@id='bidlogin']/div/div/form/fieldset/div[3]/input")
element.click()

try:
　　#ログアウトのリンクテキストを発見できたらログインOKにしました。
   WebDriverWait(driver,8).until(EC.presence_of_element_located((By.LINK_TEXT, "ログアウト")))
except:
　　#なにかしらの理由でログアウトリンクを発見できない場合の処理

def move_textbox_id(driver, id, atai):
    start = time.time()
    while driver.find_element_by_id(id).get_attribute('value')!=atai:

        driver.find_element_by_id(id).clear()
        time.sleep(1)
        
        #センドキーで値を入力する
        driver.find_element_by_id(id).send_keys(atai)
        time.sleep(1)

        if time.time()-start > 5 :
            return False   
    return True

```


ただたんにログインするだけだから簡単かと思いきや大変でした。
とくにシークレットモードで操作している場合、直接ログイン画面からログインすると絶対にログインできないです。
確かにスクレイピングでなくて手作業でログインするときも1回目のログインははじかれてました。
コピペに全角でもまざっていたのかと思って気にもとめないでいましたが。
Ansible Gathering Factsを上手く使う方法

AnsibleのGathering Factsについて、今まで熟知せずに使っていましたが、
内容を知ることで良質なplaybookが作れると感じました。

- これだけ知っておけば便利
- 結構ハマったこと

などを中心に記載します。

## 伝えたいこと

Gathering Factsとは

- 対象ホストの情報をansible_facts変数というものに格納し、tasks内の変数で使用することができる。
    - 格納された変数一覧はdebug/setupモジュールを使用することで確認できる。
- **playbook実行時**の初回に1度だけ実行される。
    - デフォルトで実行される。
        - **実行時の状態を格納する。**
    - 実行しない場合はplaybookに`gather_facts: no`と記載する。
        - playbookの実行時間が少し短くなる。
    - あるタスクで内で実行したい場合は、タスクとして記載する。
- tasks内で実行すると、実行時の環境で変数を取得する。
    - `become: yes`などを指定している場合は、実行ユーザなどの環境変数が異なる。
- 対象ホストが正常な状態でない場合にエラーになる可能性がある。

## Ansible Facts変数とは

ansible対象ホストのシステム情報などが格納された変数です。

playbookで対象ホストの情報(OS,Hostname,IP Address...)を使いたい時、この変数を用いて定義することができます。

例えば、OSがRHEL/Ubuntuによって実行したいtaskが異なる時、
Facts変数を使用することで、タスクを実行するか否かをplaybookで定義できます。

```yaml
- name: 'Install vim for CentOS 8'
  dnf:
    name: vim
    state: present
  when:
    - ansible_os_family == "Redhat"
    - ansible_distribution_major_version == "8"
```

`ansible_facts`変数一覧はdebug/setupモジュールを使用することで確認できます。

playbook内でdebugモジュールを使う

```yaml
debug: var=ansible_facts
```

ansible(CLI)でsetupモジュールを使う

```bash
ansible ${target_host} -m setup
```

## Playbook利用時のGathering Facts

Gathering Factsは、**playbook実行時**の初回に1度だけ実行されます。

デフォルトで実行されるため、実行しない場合はplaybookに`gather_facts: no`と記載します。
(playbook実行時間を少し減らすことができます。)

```yaml
- hosts: all
  gather_facts: no
  roles:
    - common
```

注意しておきたい点は、**実行時の状態を格納すること**です。
例えば、タスク内で `become: yes`で実行ユーザを切り替えた場合、格納されている変数は切り替え前のユーザのもので、切り替え後のユーザに更新されません。

task実行後にfact変数を上書きしたい場合は、以下のtaskを記載をします。

```yaml
- name: 'Gathering Facts'
  gather_facts:
```

## Gathering Factsがエラーになる場合

対象ホストからfacts変数を取得できない場合、エラーが発生します。
同様にsetupモジュールもエラーになります。
この時、対象ホストに何らかのエラーが発生しています。

試しに、対象ホストの `/etc/sudoers`にtypoを含ませてみます。

```
root		ALL = (ALL) ALL
%admin		ALL = (ALL) ALL
% typo		ALL = (ALL) ALL # わざとtypoさせた行
```

この状態でplaybookを実行するとエラーになります。

### 切り分け方法

以下のコマンドについて `gather_subset`を絞りながら実行し、
該当となるソースコードを見にいくことで、該当エラー箇所が特定できそうです。

```bash
ansible -m setup -a 'gather_subset=network,virtual,ohai,facter,hardware'
```

gather_factの処理は以下のソースコードになってます。

[ansible/lib/ansible/module_utils/facts at devel · ansible/ansible](https://github.com/ansible/ansible/tree/devel/lib/ansible/module_utils/facts)

## Reference

- [Ansible チュートリアル | Ansible Tutorial in Japanese](https://yteraoka.github.io/ansible-tutorial/)
- [変数の使用 — Ansible Documentation](https://docs.ansible.com/ansible/2.9_ja/user_guide/playbooks_variables.html)
- [gather_facts – Gathers facts about remote hosts — Ansible Documentation](https://docs.ansible.com/ansible/2.9_ja/modules/gather_facts_module.html)
- [Ansible実行が"GATHERING FACTS"で止まる - Qiita](https://qiita.com/pioho07/items/d50af79e9e7adb0dabc1)
- [OSによって処理を変えるPlaybookディレクトリの作成 - Qiita](https://qiita.com/nl0_blu/items/bb8cb9ac44fac01ea141)
YouTube Data API v3 クォータ制限について その1

<p>プログラミング初心者が自身で作りたいwebページの作成中に<br>疑問に思ったこと、問題解決したことを書いていきます。<br>間違っている点も多々あると思います。</p>

<h2>突然、YouTube Data API v3 で取得していた動画情報が取得できなくなってしまった</h2>
<p>YouTubeの動画URLを入力すればカテゴリ別に仕分けしてDBに登録し、リスト形式で表示するというwebアプリを作った。<br>
動画情報をYouTube Data API v3を用いてリスト形式で表示させるというものだったが<br>
突然動画情報が取得できなくなってしまった。
</p>

<h2>1.原因の調査</h2>
<p>原因を調査したところ、GoogleのAPIでは1日に使用できる「クォータ(Queries)(？)」の制限があるとのこと。</p>
[コンソール](https://console.cloud.google.com/apis/api/youtube.googleapis.com/quotas)

<p>こちらにアクセスしたところ確かにいっぱいだった・・・<br>
(連日上限まで気づかずに使っていたみたい・・・)</p>

![スクリーンショット 2020-11-18 5.27.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683204/f0091ca1-63b7-5d29-e24c-8e9f7d4a1950.png)

<p>1日のクォータ数の上限は10,000しかないみたい・・・<br>
上限の引き上げもGoogle側に申請できるみたいだったが、英語での申請とのことで敷居が高い・・・<br>
ならば自身のコードの見直しをしてみた。</p>

<h2>2.コードの見直し</h2>
<p>自身のwebアプリは<br>
1.youtube動画のURLをデータベースに保存<br>
↓<br>
2.データベースに保存されたURLをもとに動画情報取得（サムネイル、投稿者、タイトルなど）<br>
↓<br>
3.カテゴリ別に取得した情報を表示させる<br>
といったものだ。<br>
この「2」の箇所でAPIでの取得を行っていることが原因でクォータの上限に簡単に達してしまう模様。<br>
これでは公開したらまともに動作しなくなってしまう・・・<br></p>

<h2>3.コードの改善</h3>

<p>コードというより最早設計の問題だった。<br>
APIでの動画情報取得をできるだけ少なくするためにデータベースの保存時のみ動画情報取得するように設計し直した。<br>
1.youtube動画のURLから動画情報（サムネイル、投稿者、タイトルなど）を取得し、データベースに保存<br>
↓<br>
2.データベースに登録された動画情報を動画URLごとに表示させる<br>
これで、動画リストを開くたびにAPIが使用されることがなく、クォータの使用量もかなり余裕ができた。</p>
エラーと戦う

# pythonで出たエラーに苦戦した話
この記事は検索下手な私が「ん？これってなんのこっちゃ」ってなった体験談ww

## attribute error
~~~
AttributeError: module(object) ‘xxx’ has no attribute ‘yyy’
~~~
このようなエラーが出ることがある..

## 今回私が起こしてしまったエラーは関数の返り値がオブジェクトの際、返り値を入れるオブジェクトの内容が変わってしまった時起きた...

~~~python:sample.py
class Person:
    def __init__(self, name:str, age:int):
        self.name = name
        self.age = age

def renamed(person, pserson2):
    person.name = 'Kein'
    return person, ron

bob = Person('Bob', 19)
ron = Person('Ron', 23)
kein = renamed(bob, ron)
print(kein.name)
print(kein.age)
print(ron.name)
print(ron.age)
~~~
こんな感じで入れる変数の数が違った...

## 対処
~~~python:sample.py
class Person:
    def __init__(self, name:str, age:int):
        self.name = name
        self.age = age

def renamed(person, pserson2):
    person.name = 'Kein'
    return person, ron

bob = Person('Bob', 19)
ron = Person('Ron', 23)
kein, ron = renamed(bob, ron)
print(kein.name)
print(kein.age)
print(ron.name)
print(ron.age)
~~~
ちゃんと返り値を入れようねってことだった、

自分のコードを見ればわかる話だが、エラ〜メッセージで対処しようとすると知識がないと苦戦するかも？
可読性の高いコードを書いていきたいものだ
TypeORMを利用したカラムの一括更新

# 概要
TypeORMで多くのデータをまとめて更新しようとしたときに、大量のクエリが発行されてしまい困ったので、対処方法をまとめました。
やりたかったこととしては、以下の2つです。

1. 特定のカラムを特定値に更新
1. 特定のカラムを条件に応じた値に更新

## 1. 特定のカラムを特定値に更新

あるテーブル`table`に対して、`column1`を`value1`に更新する場合を考えます。
これは[公式ドキュメント](https://typeorm.io/#/update-query-builder)にもある通り、QueryBuilderを利用することで以下のように記述が可能です。

```typescript:sample_code_1
await getConnection()
    .createQueryBuilder()
    .update(table)
    .set({ column1: "value1" })
    .execute();
```

実際に実行されるSQLは以下のようになります。

```sql:executed_sql_1
UPDATE "table"
SET "column1" = "value1"
```
大抵は`where`句と一緒に利用されるものと思います。

## 2. 特定のカラムを条件に応じた値に更新

あるテーブル`table`に対して、以下のように条件分岐するように更新する場合を考えます。

- `column1`が`case1`の場合に、`column1`を`value1-1`に更新
- `column1`が`case2`の場合に、`column1`を`value1-2`に更新
- `column1`が`case3`の場合に、`column1`を`value1-3`に更新
- 上記以外の場合は更新しない

これはCASE文で場合分けして更新するようにします。

```typescript:sample_code_2
await getConnection()
    .createQueryBuilder()
    .update(table)
    .set({
        column1: () => (
            'CASE WHEN column1 = "case1" THEN "value1-1"' +
            'CASE WHEN column1 = "case2" THEN "value1-2"' +
            'CASE WHEN column1 = "case3" THEN "value1-3"' +
            'ELSE table.column1 END'
        )
    })
    .execute();
```

実際に実行されるSQLは以下のようになります。

```sql:executed_sql_2
UPDATE "table"
SET "column1" = CASE
    WHEN "column1" = "case1" THEN "value1-1"
    WHEN "column1" = "case2" THEN "value1-2"
    WHEN "column1" = "case3" THEN "value1-3"
    ELSE table.column1 END
```

更新対象のデータが少ない場合であれば1件ずつ更新する方法でも問題ありませんが、多くなってきた場合は上記のように一括更新する方法も検討してみると良いと思います。

#### 参考文献
[TypeORMの公式ドキュメント](https://typeorm.io/#/update-query-builder)
Note Book : Build Error OpenCV v4.5.0 with Julia

- Run `import Pkg; Pkg.add("CxxWrap")` to install the CxxWrap package.

###Install julia on ubuntu by apt-get

```test
sudo apt-get -yV install julia
```

###OpenCV build errorlog

```shell:log
z.so;/usr/lib/x86_64-linux-gnu/libdl.so;/usr/lib/x86_64-linux-gnu/libm.so (found version "1.10.4")
-- Registering hook 'STATUS_DUMP_EXTRA': /usr/local/src/opencv_contrib/modules/julia/cmake/hooks/STATUS_DUMP_EXTRA.cmake
-- Found Julia executable: /usr/bin/julia
-- Julia_VERSION_STRING: 1.4.1
-- Julia_INCLUDE_DIRS:   /usr/include/julia
-- Julia_LIBRARY_DIR:    /usr/lib/x86_64-linux-gnu
-- Julia_LIBRARY:        /usr/lib/x86_64-linux-gnu/libjulia.so.1
-- JULIA_HOME:           /usr/bin
-- Julia_LLVM_VERSION:   v8.0.1
-- Julia_WORD_SIZE:      64
-- Found Julia: /usr/lib/x86_64-linux-gnu/libjulia.so.1 (found version "1.4.1")
ERROR: ArgumentError: Package CxxWrap not found in current path:
- Run `import Pkg; Pkg.add("CxxWrap")` to install the CxxWrap package.

)
```

```shell:

$ Julia
julia> import Pkg
julia> Pkg.add("CxxWrap")
    Cloning default registries into `~/.julia`
    Cloning registry from "https://github.com/JuliaRegistries/General.git"
      Added registry `General` to `~/.julia/registries/General`
  Resolving package versions...
  Installed libcxxwrap_julia_jll q v0.8.0+0
  Installed CxxWrap qqqqqqqqqqqqqq v0.11.0
  Installed MacroTools qqqqqqqqqqq v0.5.6
Downloading artifact: libcxxwrap_julia
   Updating `~/.julia/environments/v1.4/Project.toml`
  [1f15a43c] + CxxWrap v0.11.0
   Updating `~/.julia/environments/v1.4/Manifest.toml`
  [1f15a43c] + CxxWrap v0.11.0
  [1914dd2f] + MacroTools v0.5.6
  [3eaa8342] + libcxxwrap_julia_jll v0.8.0+0
  [2a0f44e3] + Base64
  [ade2ca70] + Dates
  [b77e0a4c] + InteractiveUtils
  [76f85450] + LibGit2
  [8f399da3] + Libdl
  [56ddb016] + Logging
  [d6f4376e] + Markdown
  [44cfe95a] + Pkg
  [de0858da] + Printf
  [3fa0cd96] + REPL
  [9a3f8284] + Random
  [ea8e919c] + SHA
  [9e88b42a] + Serialization
  [6462fe0b] + Sockets
  [cf7118a7] + UUIDs
  [4ec0a83e] + Unicode
julia>
```

###cmake
```
cmake \
-DWITH_JULIA=ON \
-DJlCxx_DIR=~/.julia/registries/General \
..
```
Django で models.Modelにクラスメソッドを追加する

# はじめに
Modelを継承してクラスメソッドを追加したかったのですが、手こずったので備忘録。

## やりたかったこと
- 各modelに、条件に合致するオブジェクトが存在するか確認するis_existsメソッドを追加

## 前提
- Django == 3.1.3


# How to
Pythonでクラスメソッドを追加する方法は複数あります
TestClass に test_method を追加したい場合、

### パターン1
```python
def test_method(cls):
   ...

TestClass.test_method = classmethod(test_method)

TestClass.test_method()
```

### パターン2
```python
class MyTestClass(TestClass):
    @classmethod
    def test_method(cls):
        ...

MyTestClass.test_method()
```

今回は、パターン2のクラスを継承して追加する方法で行います。
### コード
```models.py
from django.db import models
class MyModel(models.Model):
    @classmethod
    def is_exists(cls, **kwargs):
        try:
            obj = cls.objects.get(**kwargs)
        except cls.DoesNotExist:
            return None
        else:
            return obj
    class Meta:
        abstract = True

class Hogehoge(MyModel):
    name = models.CharFields(max_length=100)
    ...
```

注意すべき点は Metaクラスのabstractです。
models.pyに記述した場合、このクラスそのものがModelだと認識されてしまうため、エラーが出ます。(The field ** clashes with the field ** from model **.)
そのため、Djangoに抽象モデルだと認識してもらう必要があり、それがabstractです。
UbuntuでMySQLの外部公開とログイン

このタイトルのような記事は多く存在するのですが，Ubuntuでの例が少ないのか，
一筋縄では行かなかったので記事にすることにしました．

# 環境

||Version|
|:-:|:-:|
|ホストOS|Ubuntu Server 20.04.1 LTS|
|ホスト側MySQL|Ver 8.0.22|
|クライアント側MySQL(MariaDB)|10.3.23-MariaDB|

今回クライアント側は`Raspberry Pi`を使用していたので，`mariaDB`を使用しています(raspbianにはmysqlが入らなかった？)．
MySQLとmariaDBはほぼ互換なので，MySQL8系同士でやるなら問題ないと思います．

しかし，MariaDBの10.3はMySQLの5.7に相当するそうなんですが，
5系から8系にログインする際には問題が発生するのでそれについても以下で解説します．

ホスト側とクライアント側にそれぞれMySQLはインストール済みとします．

# [ホスト側] 外部公開の設定

デフォルトではlocalhostしか接続できない設定になっているので，公開範囲を設定します．
`/etc/mysql/mysql.conf.d/mysqld.cnf`にアクセスして，`bind-address`のところを以下のようにします．

```bash
$ sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
```

```bash:/etc/mysql/mysql.conf.d/mysqld.cnf
bind-address                    = 0.0.0.0
default_authentication_plugin=mysql_native_password #クライアント側が5系の時にはこの行も追加．8系の時は不要．
```

設定が終わったらMySQLを再起動します．

```bash
$ /etc/init.d/mysql restart
```

# [ホスト側] 接続用のユーザを作成

MySQLにログインし，以下のコマンドでユーザを作成します．
ここでは`admin`がユーザ名，@以降の`'%'`は任意のIPアドレスを意味します．

```sql

CREATE USER 'admin'@'%' IDENTIFIED BY 'P@ssw0rd';
GRANT ALL ON *.* TO 'admin'@'%';
```

以下のコマンドで確認しましょう．

```sql
select user,host from mysql.user;
```

次のようになっていたらOKです．

```
mysql> select user,host from mysql.user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| admin            | %         |
| debian-sys-maint | localhost |
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
```

# リモート側からログイン

リモート側からログインしてみましょう．

```
$ mysql -u admin -h [IPアドレス] -p
```

リモート側がMySQL8系ならこれでログインできると思います．

# MySQL5系から8系にログインする

もしリモート側が5系の場合，以下のようなエラーがでると思います．

```
ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded: /usr/lib/arm-linux-gnueabihf/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory
```

これは認証プラグインが8系で変更されてしまったためです．
今回はホスト側の認証プラグインを5系で使用されていたものに変更する形で解決したいと思います．

MySQLの設定に次を加えます．
(上の設定ではこちらを加えた状態で記載しました)

```bash
$ sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
```

```:/etc/mysql/mysql.conf.d/mysqld.cnf
default_authentication_plugin=mysql_native_password
```

設定が終わったらMySQLを再起動します．

```bash
$ /etc/init.d/mysql restart
```

これで先程と同じようにユーザを作成することで，認証プラグインが変更されます．
確認してみましょう．

```
mysql> select user,host,plugin from mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| admin            | %         | mysql_native_password |
| debian-sys-maint | localhost | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | auth_socket           |
+------------------+-----------+-----------------------+
```

---

# 参考URL

https://qiita.com/katzueno/items/e735950c7440f232ef27
https://sys-guard.com/post-8501/
https://symfoware.blog.fc2.com/blog-entry-2159.html
https://www.s-style.co.jp/blog/2018/05/1807/
Github Actionsを使って自動テストをした話

# はじめに
今回はGithub Actionsを使って自動テストをした話を紹介していきたいと思います。

# 自動テストのタイミング
PR出したタイミングとかPR出したブランチにpushしたタイミングでいいのでは？
と思う方もいるかもしれません。

Github Actionsはpublicなレポジトリだと無料ですが、Organizationで使うと従量課金制になっています。
テストの量が多い場合、push毎にCIを走らせてしまうととんでもない実行時間になってしまいます。

またPR出したタイミングで修正があることに気付き新しくpushした場合、その部分はグリーンになっている保証はありません。

なので今回はレビュワーがapproveしたタイミング(LGTMしたタイミング)で自動テストを回すようにしました。

PR出す→修正がある場合は新たにpush→レビュワーがapprove→テスト→成功でも失敗でもslackに通知

# レビュー時にテストをする方法
自動テストのやり方などはググればたくさん出てくるんですが、approveされたらという条件が合致するものがなかったので苦労しました。

まず[Github Actionsのトリガー](https://docs.github.com/ja/free-pro-team@latest/actions/reference/events-that-trigger-workflows#pull_request_review)を見てみると、pull_request_reviewというのが出てきます。
これがレビューされた時のトリガーです。

今回筆者はアクティビティタイプをsubmittedだけにしました。
レビュワーがapproveしてくれたけど、コメントを編集した場合や、取り消しした場合に毎回走るのは嫌だったので追加したタイミングだけCIが走るようにしました。

次に[プルリクエストをレビューした時のWebHook](https://developer.github.com/webhooks/event-payloads/#pull_request_review)を見ていきます。
ここのpayloadを見ていくと、reviewの中にstateというのがあるのがわかります。
ここには

- commented
- approved
- change_requested(これ合ってるかわからない)

の3つの要素が入ってきます。

なのでこれがapprovedの時だけCIを走らせればいい感じですね。

一旦全体を見ていきましょう

```yaml

name: UnitTest

on:
  pull_request_review:
    types: [ submitted ]
    branches: [ master ]

jobs:
  test:
    if: github.event.review.state == 'approved'
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8
      - name: UnitTest
        run: ./gradlew testDebugUnitTest
```


# 細かい解説

## トリガー

```yaml

on:
  pull_request_review:
    types: [ submitted ]
    branches: [ develop ]
```

まずはトリガーから
レビューをした時に走らせたいのでpull_request_review
アクティビティタイプはsubmitted
ブランチは適当にmaster指定にしてますが、任意で設定してください  

## 条件

```yaml
jobs:
  test:
    if: github.event.review.state == 'approved'
    runs-on: ubuntu-latest
```
  
次にテストを走らせる条件
jobsをスタートしてジョブ名はtest(ここも任意で)
ifに条件を書いていきます。
github.eventでそのトリガーに合ったWebHookのペイロードを取得できます。
今回は上記でも説明したようにreviewの中のstateを使いたかったのでgithub.event.review.state

ちなみに記法として2パターンあって

```yaml

if: github.event.review.state == 'approve'
```

でも

```yaml

if: ${{ github.event.event.review.state == 'approve' }}
```

でもOK
確かシングルクオーテーションじゃなきゃダメだったので気をつけてください

# あとはいつも通り

```yaml
steps:
      - uses: actions/checkout@v2
      - name: set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8
      - name: UnitTest
        run: ./gradlew testDebugUnitTest
```

Androidのビルド環境を作ってテストするだけ
テストコマンドは

``./gradlew test{buildVariantName}UnitTest
``

です。

# まとめ
以上がレビューでapproveもらった時だけ自動でテストを走らせる方法です。

次はテスト結果をslackに通知する方法でいいかな？
ReactでJSONデータをmap型で扱うときの注意点


## APIからJSONを取得

```javascript

    componentWillMount(){
        console.log("getpod")
        const request = axios.create({
            baseURL: "http://127.0.0.1:8080",
            method: "GET"
        })

        request.get("/getpods")
            .then(request => {
                // console.log(request.data)
                this.setState({
                    pods: request.data.items
                })
                console.log(this.state.pods)
            })
    }
```

## JSONの要素を取り出す

```javascript

                    <div>
                        <ul>
                            {this.state.pods.map((pod) => {
                                return <li>{pod.metadata.name}  {pod.status.phase}</li>;
                            })}
                        </ul>
                    </div>
```

## 取得されたJSONデータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/80a43431-0967-1408-0b84-0177f50eabde.png)

## 注意ポイント
- `reqest.data` とすると、一番はじめの要素がルートというか頭の部分になるのだけど、renderするときに`pod.items.metadata.name`みたいなことをやってもエラーになった
- `request.data.items`とすると、一番はじめの要素がmap形式になるようで、renderするときにその次の要素から指定すればエラーはでなかった
- つまるところ、stateにいれる値はmap型の階層まで定義してあげて、その部分から下の要素を普通に指定してあげればいいみたい
    - そのため、取得したJSONデータの中に複数の層にまたがって必要なデータがある場合、stateを複数定義してあげてmap形式の階層で定義してあげればよいみたい
- いまいちなんでかはわからない
M5StackでNeopixel六角ユニットをLチカしてみる！

そろそろイルミネーションが見られる季節になってきましたね🎄
ということでLチカしてみようと思い、手軽に始められるM5StackとNeopixelで簡単なデモを作ってみました！✨


完成したのはこちら。


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5Stack Core2でNeopixel六角ユニットを点灯させてみました！<a href="https://twitter.com/hashtag/M5stack?src=hash&amp;ref_src=twsrc%5Etfw">#M5stack</a> <a href="https://t.co/OMwmiYI7lF">pic.twitter.com/OMwmiYI7lF</a></p>&mdash; まえぷー@出窓菜園 (@kmaepu) <a href="https://twitter.com/kmaepu/status/1328732871364788226?ref_src=twsrc%5Etfw">November 17, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


#レシピ

今回はビジュアルプログラミングツールの「[**UIFlow**](https://flow.m5stack.com/)」を使用しました。

部材はこちら。

- [M5Stack Core2](https://www.switch-science.com/catalog/6530/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/7e1a7984-ea8a-1a66-b676-aaf14bd7cae0.png)

- [M5Stack用NeoPixel互換LED搭載 六角形ユニット](https://www.switch-science.com/catalog/6058/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/d96e9463-8e94-5e7d-998c-296052b7328b.png)


#料理する
##UIFlowにアクセスする
UIFlowの環境構築は次のサイトが参考になりますので、ここでは省略します。

- [ようこそ UIFlow へ！flow.m5stack.com](https://m5stack.github.io/UIFlow_doc/ja/)
- [UIFlow ＋ M5Stack Core2 を試す（ファーム： Beta2-core2）【準備編＋α】](https://qiita.com/youtoy/items/8d257e49326bb41e3eda)

UIFlowのエディタを開くとこのような画面となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/bd4517a4-7c06-656a-0770-bea71d390b35.png)

##Neopixel六角ユニットのブロックを読み込む
デバイスが表示されている下に＋マークがあるので、それをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/f32182f0-adec-8203-ed51-5a95e09e83db.png)

続いてどのユニットを読み込むか選択する画面が開きます。ここでは「**RGB LED**」を選択します。PortはAで、Numberは37を指定します。これはM5Stack Core2のGrove PortがAで、接続するNeopixel LEDの個数が37個という意味です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/b9f9c15b-c841-c657-d8f2-87a18c5b2a33.png)

追加に成功すると、ブロックリストのUnitsの中に、「RGB LED」という項目が増えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/fa1f865b-9be3-4a1e-778f-c7ed0722d849.png)

##とりあえず何か点灯させてみる
RGB LEDカテゴリを開き、下にスクロールするといかにもそれらしいブロックがあるので追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/620dce48-0443-7f0b-1db6-5295f470b740.png)

升目をクリックするとチェックマークがつきます。このLEDが右上に表示されている色で点灯します。試しに矢印を表示字てみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/9af51efd-838f-9bf9-0f9a-6775c00a30cb.png)

実行すると次のように点灯します！
![20201118_005654.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/0043c8b8-8fbd-4a6e-bc3f-7d2d02f11ec3.jpeg)

##別のブロックも使用してみる
他にも次のようなプログラムで使いやすいブロックや、全体点灯などのブロックがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/f5020586-6c9c-7991-d9d9-47f4d9e895ed.png)

試しに全体点灯（色変更）と、LED単体を別の色に変えていくフローを作成してみました。
フローは次の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/eb81e1cf-14a7-7572-b562-8eede40b438b.png)

処理を説明すると、

- 起動すると全て青色に点灯し、1.5秒待つ。
- 全て緑色に点灯し、1.5秒待つ。
- LEDt単体点灯を37回繰り返す。

です。

#おわりに
面倒なはんだ付けやプログラミングの手間がなくここまでできたのは感激です！
これを使ってオリジナルの🎄クリスマス🎄オーナメントを作ってみるのも面白いですね！

それでは良きM5Stackライフを！
網掛けのborderを使う

網掛けのborderを使う

```css
.parent {
    display: flex;
    justify-content: center;
    align-items: center;
}

.sample {
    border: 2px dashed #5b8bd0;
    width: 350px;
}
```

```react
import React from 'react'
import './Hoge.css'

export const Hoge = () => {
    return (
        <>
            <div className="parent">
                <div className="sample">
                    <ul>
                        <li>ああああああああああ</li>
                        <li>ああああああああああ</li>
                        <li>ああああああああああ</li>
                        <li>ああああああああああ</li>
                    </ul>
                </div>
            </div>
        </>
    )
}
```

結果

![スクリーンショット 2020-11-18 1.29.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/0804dfa4-af2e-979f-3d3e-9efc8d9d8c29.png)
ヘッダーを追従させるcss

ヘッダーを追従させるcss

・position: fixedを使って位置を固定する
・ヘッダーの後ろに他の要素が回り込まないようにbodyにヘッダーの高さだけmarginを入れる

```css
body {
  margin: 50px 0 0 0;
}

.header {
    background-color: coral;
    position: fixed;
    width: 100%;
    height: 50px;
    top: 0;
    left: 0;
}

.dummy {
    width: 250px;
    height: 250px;
    margin-bottom: 30px;
    background-color: wheat;
}
```

```react
import React from 'react'
import './Hoge.css'

export const Hoge = () => {
    return (
        <>
            <div className="header">
            </div>
            <div className="dummy">dummy</div>
            <div className="dummy">dummy</div>
            <div className="dummy">dummy</div>
            <div className="dummy">dummy</div>
            <div className="dummy">dummy</div>
            <div className="dummy">dummy</div>
            <div className="dummy">dummy</div>
            <div className="dummy">dummy</div>
            <div className="dummy">dummy</div>
        </>
    )
}
```

結果
![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/1ed25f71-cc5e-7034-8a18-f5ea8b8e4d62.gif)
cssで回転アニメーション

・transform: rotate(1turn);というアニメーションを使うと要素が1回転する

```css
.parent {
    width: 100vw;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

.anim {
    background-color: aqua;
    width: 100px;
    height: 100px;
    animation: rotate 3s linear infinite;
}

@keyframes rotate {
    100% {
        transform: rotate(1turn);
    }
}
```

```react
import React from 'react'
import './AnimPage.css'

export const AnimPage = () => {
    return (
        <>
            <div className="parent">
                <div className="anim"></div>
            </div>
        </>
    )
}
```

結果
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/d3e6c4ed-4e28-41b2-c021-0afcb386143f.gif)
文字列からN番目

#[Ruby] 文字列からN番目
#問題
半角アルファベット文字列 s と 整数 n が入力されます。

文字列 s の1番左の文字を 1 文字目とし n 文字目のアルファベットを出力して下さい。

例えば
paiza 3
と入力された場合
i
と出力して下さい。
#入力される値
入力は以下のフォーマットで与えられます。

s n
#期待する出力
文字列 s の n 文字目を出力して下さい。
#入力例1
thankyou 3
#出力例1
a
#入力例2
abcdefghij 5
#出力例2
e
#私の答え
```java:
s = gets.split(" ").map(&:chomp)
a = s[1].to_i
puts s[0].slice(a - 1)
```
#今回のポイント
###1行目で入力例１の場合だと [thankyou, 3] と分割させている
###2行目でa変数に 5 を代入している
###3行目で thankyou をsliceメソッドで5番目の文字列を指定している。ここを (a) のままだと0からカウントされる為 -1 をして調整している
#以上！
URL→QR→PDF  for VBScript

これは何かというと
--
URL文字列をQRコードにしてPDFで保存するVBScriptです。
以前作った以下の記事の焼き直しです。
（必要な環境も前回に準じます。Microsoft Office (Excel + Access) 2016 以降、のはず。）

>[QRコードにしてクリップボードに格納するExcelマクロ](https://qiita.com/jinoji/items/f1fe9cfa2c7585b400ae)

コード
--

```vb:QRPDF.vbs

QRPDF "Qiita", "https://qiita.com/", "Qiita_QR"

'URL文字列をQRコードにしてPDFで保存する関数
Function QRPDF(strTitle, strURL, strFileName)
    Dim app, wb, ws
    Dim wTitle, wQR, wURL
    
    Set app = CreateObject("Excel.Application")
    Set wb = app.Workbooks.Add
    Set ws = wb.Worksheets.Add
    
    With ws
        Set wTitle = .Range("A1")
        Set wQR = .Range("A2")
        Set wURL = .Range("A3")
    End With
    
    With ws.OLEObjects.Add("BARCODE.BarCodeCtrl.1")
        .Object.Style = 110
        .Top = wQR.Top
        .LinkedCell = wURL.Address
        .Width = .Height
        wQR.RowHeight = .Height
        wTitle.Value = strTitle
        wURL.Value = strURL
        wURL.EntireColumn.ColumnWidth = 30
        wURL.ShrinkToFit = True
    End With
    
    With ws.PageSetup
        .PrintArea = ws.UsedRange.Address
        .Orientation = 2 'xlLandscape
        .Zoom = 300
    End With
    ws.ExportAsFixedFormat 0, strFileName   '0: xlTypePDF

    wb.Close False
    app.Quit
End Function
```
結果イメージ
--
![QR.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164214/c4968e89-f45a-d1c9-d79f-7b6dadb58a32.png)



今後の展開
--
以下の記事の処理と組み合わせて、Web会議のURLをQRコード化するVBScriptを作る予定です。
>[Outlookから直近の予定一覧を取得してメール（VBScript/Excelマクロ）](https://qiita.com/jinoji/items/c6de69523394da3f28be)
【Tips】pyenvでPython3系の3.5.3未満をインストールしようとしたときに発生するエラーへの対処

# 問題：Pythonインストールにおけるエラー
## 入力
```shell
pyenv install 3.4.8
```

## 出力
```shell
Downloading Python-3.4.8.tar.xz...
-> https://www.python.org/ftp/python/3.4.8/Python-3.4.8.tar.xz
Installing Python-3.4.8...
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?

Please consult to the Wiki page to fix the problem.
https://github.com/pyenv/pyenv/wiki/Common-build-problems


BUILD FAILED (Ubuntu 18.04 using python-build 1.2.19-1-gece59ca8)

Inspect or clean up the working tree at /tmp/python-build.20201118000548.3700
Results logged to /tmp/python-build.20201118000548.3700.log

Last 10 log lines:
(cd /home/【ユーザ名】/.anyenv/envs/pyenv/versions/3.4.8/share/man/man1; ln -s python3.4.1 python3.1)
if test "xupgrade" != "xno"  ; then \
        case upgrade in \
                upgrade) ensurepip="--upgrade" ;; \
                install|*) ensurepip="" ;; \
        esac; \
         ./python -E -m ensurepip \
                $ensurepip --root=/ ; \
fi
Ignoring ensurepip failure: pip 9.0.1 requires SSL/TLS
```

# 環境
- Ubuntu 18.04 LTS (Windows 10 2004 WSL1上環境)
- anyenv
    * pyenv 1.2.19-1-gece59ca8

# 原因：OpenSSLの対応バージョン
Python3系のの3.5.2まではOpenSSLの1.1に未対応。

# 解決方法：OpenSSLのダウングレード
```shell
sudo apt install libssl1.0-dev
pyenv install 3.4.8
```

# 補足
## 1. 事後処理
OpenSSL1.0をインストールすることでOpenSSLがダウングレードしてしまう。
Pythonのインストールが無事終了したら以下を実行。

```shell
sudo apt install libssl-dev
```

## 2. Rubyの場合
Rubyにおいても2.4未満で同様の原因によるエラーが発生する。
くわしくは[こちら](https://qiita.com/GandT/items/544cc07faa69ac959028)の記事を参照。

# 参考文献
- [pyenvでinstallできない](https://qiita.com/pokotsun/items/3ebab483b0e134ab1726)
- [ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?](https://github.com/pyenv/pyenv/issues/950)
- [【Tips】rbenvでRuby2.4.0未満をインストールしようとしたときに発生するエラーへの対処](https://qiita.com/GandT/items/544cc07faa69ac959028)
自宅でプロジェクションマッピングやっちゃおう

# プロジェクションマッピングとは
プロジェクションマッピングとは、プロジェクタを使用し、空間と映像を合成して新しい空間演出をするものです。
Projection Mapping
  (映写)    (対応付け)

つまりは、スクリーンの形状に合わせたコンテンツの投影こそが、プロジェクションマッピングらしいです。

# 環境構築
今回使用する機材
・ **PC**
MacBook Pro
プロセッサ : 2GHz クアッドコアIntel Core i5, メモリ : 16GB, MacOS Catalina (10.15.4)

・ **プロジェクタ**
[POYANK ](https://www.amazon.co.jp/gp/product/B079FSKZN8/ref=ppx_yo_dt_b_asin_title_o01_s01?ie=UTF8&psc=1)
・ **照射対象物**
なんでも良い
・ **プロジェクションマッピング用ソフトウェア**
MadMapper

# いざプロジェクションマッピング
## プロジェクションマッピング用ソフトウェアの準備
今回使用するソフトウェアは、[MadMapper](https://madmapper.com/)と呼ばれるものです。
こちらのソフトは、プロジェクションマッピング用のソフトということもあり、投影する際の映像の演出や写し方を簡単に制御できるソフトです。
また、Demo版は無料なので、そちらを使用しました。
有料版ですと、価格が50000円くらいになります。

## 照射対象物を配置
今回は、下記の箱を利用しました。
表面が白く照射のしがいがあります。

![IMG_8332.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/301f27fd-3d87-a2d0-1fd3-9fce21faf387.jpeg)

## プロジェクタの準備
今回は家にあった下記のプロジェクタを利用しました。
HDMIでMacと接続していただき、ミラーリングではなく拡張画面の設定にしておきます。
ちなみにリンクは、[POYANK](https://www.amazon.co.jp/gp/product/B079FSKZN8/ref=ppx_yo_dt_b_asin_title_o01_s01?ie=UTF8&psc=1)という、格安のプロジェクタを映画を見るように使用しているのですが、こちら機能的にはとても満足しております。
![IMG_8333.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/152dfc41-cad9-3032-0001-9f407d964512.jpeg)

## プロジェクションマッピングの設定
### タブ操作
基本的なタブの操作は下の二つで行っていきます。
![スクリーンショット 2020-11-18 0.23.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/202099f2-b542-8eb2-e05b-c4368b124aae.png)

### プロジェクタの設定
プロジェクタの設定は下記の通りで、プロジェクタタブを選択後、Projecter-1を選択し、Destinationを自身のプロジェクタの名前にするだけで大丈夫です。
![スクリーンショット 2020-11-18 0.28.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/62e7a71c-1aa4-32c1-77bd-18574cf81861.png)

### コンテンツの設定
[照射するコンテンツ(OutPut)] にて、実際に照射対象物に照射しながらコンテンツの位置を調整する形になります。

![スクリーンショット 2020-11-18 0.32.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/4ec4cd44-7b3f-4a5b-b073-f2e95a031641.png)

### プロジェクタによる照射
プロジェクタの投影方法は、output → Full Screen Modeを選択することで行えます。
![スクリーンショット 2020-11-18 0.37.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/d981a557-6aee-dfe8-d97a-2068732e15fd.png)


## 実際に作成したプロジェクションマッピング
![projection.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/8b734cf2-7a87-f700-4694-2eb318c6b93d.gif)
Laravel で「Server error: GET http://cabinet.laravel.com/latest.zip resulted in a 522 Origin Connection Time-out response:」エラー

Laravel で久しぶりに laravel new blog のコマンドを打ってプロジェクトを作ろうとしたらタイトルのエラーが発生した。

```
laravel% laravel new blog
Crafting application...

In RequestException.php line 113:
                                                                               
  Server error: `GET http://cabinet.laravel.com/latest.zip` resulted in a `52  
  2 Origin Connection Time-out` response:                                      
  <html>                                                                       
  <head><title>522 Origin Connection Time-out</title></head>                   
  <body bgcolor="white">                                                       
  <center><h1>522 Origin Conne (truncated...)                                  
                                                                               

new [--dev] [--auth] [-f|--force] [--] [<name>]
```

#困ったらstackoverflow
Laravel News に載っている通りインストーラーアップデートしなさいって書いてありました。
https://stackoverflow.com/questions/64686037/why-do-i-get-a-laravel-error-while-creating-a-new-project

```ruby:解決方法
composer global require "laravel/installer:^4.0"
```

上ので私は解決しました。それでダメならアンインストールとインストールとか試しなさいだそうです。

【詳細は下記参照】
https://laravel-news.com/updating-the-laravel-installer
SQL Server メモ書き

##SQL Server メモ書き 2020/11/18
####1.Auto Increment(IDENTITY) が採用されているテーブルの次に割り振られるIDの確認をする。

```
SELECT IDENT_CURRENT('[TABLE]') AS ID
```
####2.IDENTITYが採用されているテーブルのIDの現在地を現在のID値にリセット
```
--[SATORU] にはテーブル名を入力
DBCC CHECKIDENT ([TABLE], RESEED, 0); -- 実IDを 0 にリセット
DBCC CHECKIDENT ([TABLE]);            -- カウンタのIDを最大値にリセット
DBCC CHECKIDENT ([TABLE], NORESEED);  -- 実IDとカウンタIDチェック
```
HTTPのGET/POSTをcURL(コマンド)とPython(プログラミング)で比較


#HTTP GET/POST
HTTPのGETをサーバーから情報を取得してきます。JSONファイルなどを返してくれる
HTTPのPOSTはサーバーに情報を送ります。特に返ってくるものはない(成功、失敗が返ってくることがある)

#cURLとPython
cURL(コマンド)でHTTPのGET/POSTを使えるけどプログラミング(Python)に落とし込める方法がわからない人向けです。
PythonはPython3のurllibライブラリを使用しています。

#HTTP GET
複数のheaderも付け加えられています。
「-H」がcURLのheaderです。

```shell
curl -X GET "https://example.com/api/" -H "accept: application/json" -H "Content-Type: form"
```

```python
from urllib.parse import urlencode
from urllib.request import urlopen, Request

url = "https://example.com/api/"

headers = {
    "accept" :"application/json",
    "Content-Type" :"application/x-www-form-urlencoded"
}

request= Request(url, headers=headers)

with urlopen(request) as response:
    body= response.read()
    print(body)
```

#HTTP POST

複数のdataが付け加えられています。このdataがサーバーに送信されます。
「-d」がcURLのdataです。

```shell

curl -X POST "https://example.com/api/" -H "accept: application/json" -d "temperature=18" -d "operation_mode=auto"
```


```python
from urllib.parse import urlencode
from urllib.request import urlopen, Request

url = "https://example.com/api/"

headers = {
    "accept" :"application/json"
}

request = Request(url, headers=headers)

data = {
    "temperature": "18",
    "operation_mode": "auto",
}

data = urlencode(data).encode("utf-8")

response = urlopen(request, data)
```
#あとがき
HTTP GET/POSTは詳しくはわかっていないため最小限の説明に抑えましたが、コート自体はあっていると思います。
HTTP GET/POSTのことは他で調べてみて下さい。APIなどを利用すると出てくると思います。
Webpackまとめ

##Webpackとは？
- モジュールバンドラのこと。

##モジュールバンドラとは?
- 複数のモジュールを1つにまとめたファイルを出力するツールのこと(※出力設定によっては複数のファイルを出力することもあります)

##webpack以外にモジュールバンドラはあるの？
- Browserify
- RequireJS

##使うメリットは？　3つあります
1. webpackが依存関係を考慮して１つのファイルにまとめてくれるので、開発者は依存関係を一切把握する必要はなくなりました。
1. また、ファイルが１つになることでブラウザがWebアプリケーションを提供する時に読み込むファイルが減り、これに伴いHTTPリクエストの回数も減ることでユーザーに素早く画面を提供できるようになる。
1. HTTPリクエストの効率は、要求されているファイルの数とサイズに正比例しますので、大規模なWebアプリケーションになるほど、Webpackの役割は重要になります。


##どこで使えるの？
Node.jsの実行環境で使えます

##どうすれば使えるの？
npmコマンドから導入し、コマンドを実行すれば使えます（下は開発環境のみで使う場合）

`$ npm install webpack webpack-cli --save-dev`

##設定ファイルは？
 webpack.config.js

##まだピントこないんだけど。。。

- 複数のjsファイルを書いた後に、コマンドでそれら全てのjsをまとめた1つのファイルをつくるよ。

- ブラウザに表示するときはそのファイルだけを読むから表示も早くなる

これでイメージ湧きますか？:sweat_drops:

##そもそもwebpackが必要になったの？

JavaScriptが人気になり、規模が広がりたくさんの機能が生まれた結果
依存性の解決、必要な時に機能を使うための仕組みが必要になったから

##JavaScriptのモジュールの歴史

JavaScript のプログラムはとても小さいものから始まりました。
初期の用途は、jqueryなど必要に応じてウェブページにちょっとした動きを追加する独立したスクリプト処理がほとんどでした。

今や大量のJavaScriptで書かれたアプリケーションまで生まれるようになりました。（Angular , Reactなど）

そのため近年は、JavaScript プログラムをモジュールに分割して必要な時にインポートできるような仕組みの提供が検討されるようになったのです。

Node.js(2011~)は長年この機能を提供しています。
モジュールの利用を可能にする JavaScript ライブラリーやフレームワークも数多くあります
 (例えばCommonJS やRequireJS など最近では Babel)。

2015年にES modulesというES2015仕様において策定された、JavaScriptファイルから別のJavaScriptファイルを読み込む仕組みが生まれました。

webpackの場合はこの標準仕様のES Modulesが使えたり、node_modulesのモジュールを結合できるといったメリットがあります。
詳しくはこちら
[JavaScriptのモジュールシステムの歴史と現状](https://qiita.com/mizchi/items/6b569cc75dbcc26a1f15)

参考記事
---
[ES modulesとは](https://app.codegrid.net/entry/2017-es-modules-1)
[JavaScriptのモジュールの歴史
](https://uuuundefined.tokyo/blog/javascript-modules/)

[webpackを利用してみる（入門編）](https://www.mitsue.co.jp/knowledge/blog/frontend/201912/05_0000.html)
ガンダムっぽいカラースキームをつくってみた（vim）

## おもいつき

vimって「中の人に命令する」とか「ロボットを操作する」イメージで語られることも多い。そんなイメトレをしながら訓練してる。ほな、ガンダム色のカラースキーム、あるんちゃうかと思ったけど、これが意外とない。ので、つくってみた。


## カラーテーブル

Solarizedの各色を置き換え（ダークで使っているもののみ）。

| name | Solarized | ガンダムっぽい |
|:-:|:-:|:-:|
| base03  | 002B36 | 2A2C29 |
| base02  | 073642 | 323431 |
| base01  | 586E75 | 8EA2A0 |
| base00  | 657683 | → |
| base0   | 839496 | D9D9D9 |
| base1   | 93A1A1 | → |
| base2   | EEE8D5 | → |
| base3   | FDF6E3 | → |
| Yellow  | B58900 | F0D900 |
| Orange  | CB4B16 | E54E11 |
| Red     | DC322F | DE3C30 |
| Magenta | D33682 | D87093 |
| Violet  | 6C71E4 | 84469A |
| Blue    | 268BD2 | 0066B0 |
| Cyan    | 2AA198 | 008DC2 |
| Green   | 719E07 | 00A44B |

いまのところはベタに手打ちしてる。Solarizedではない、ちょうどいいカラースキームを探してきて、フォークしてつくるとよいのだろうなあ。


## スクリーンショット

![スクリーンショット 2020-11-18 0.02.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/e729cdf1-baba-db68-5e66-6499f6929a09.png)
![スクリーンショット 2020-11-18 0.04.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/f42d6f24-a1f8-c0d8-6369-6c3eb2a51b21.png)
![スクリーンショット 2020-11-18 0.18.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/4bb76326-457b-8578-c63e-dd9ffa077f2e.png)

## リソース

[機動戦士ガンダム THE ORIGINのサイト]
(http://gundam-the-origin.net/products/book.html)　から画像をかりてきて、

[pictones]
(https://pictones.firebaseapp.com)　でカラーコードを抽出（8色）。
[TIPS]UnityのML-Agentsに関する情報ざっくりまとめ

# 最初に

どうも、ろっさむです。

今回はUnityで機械学習を行う際に使用できる有名なオープンソースプラグインである**「ML-Agents」**に関して調べたことをざっくりまとめた記事となります。

「機械学習かー、興味はあるんだけどねー…でもUnityでできるなら…」

という方の、導入になれば幸いです。
（自分がそうです）

# ML-Agentsとは何か

Unity初の機械学習ができる**オープンソースプラグイン**であり、正式名称は**「Machine Learning Agents」**となります。2017年9月17日にリリースされて以降、現在もアップデートを重ねています。
気になるGitHubのリンクは以下となります。

https://github.com/Unity-Technologies/ml-agents

Unityでの公式ページは以下の通りです。

https://unity3d.com/jp/machine-learning

このプラグインの目的としては、**機械学習の最新の技術をゲーム開発者がUnityをプラットフォームとして扱えるようにすること**です。
上記のライブラリの中には**エージェント（学習者）を定義するためのC#のSDKと、2D、3D及びVR/AR環境用のエージェントをトレーニングするための最先端の機械学習ライブラリ**が含まれています。
ここでのC#のSDKはゲームやUnity環境に簡単に組み込めるようになっており、APIも機能が豊富で、安定しているようです。
ライブラリは4つのパッケージで構成されており、1つのUnityパッケージと3つのPythonパッケージとなっています。
フレームワークの内部では**UnityとPython間の通信を行っており、Pythonパッケージ側で機械学習アルゴリズムを使用してゲーム内のキャラクターを学習させる**ことができます。

今後の展望として、ML-Agentsを使用してローカルマシンで機械学習を行うことには限界があるため、クラウドサービスを提供し、ML-Agentsのユーザーがスケーラブルなクラウド環境で機械学習を行うことができるようにしていくみたいです。これによって、トレーニングを多数のマシンで同時に行ったりして、より速く結果を求められるようになります。
ML-AgentsCloudへの早期アクセスも始まっているみたいです。

ML-Agentsを使用することで、**2つの深層強化学習アルゴリズム、Proximal Policy Optimization（PPO）とSoft Actor-Critic（SAC）を使用したトレーニングが可能**となります。

「なんだか難しそうな単語が並んでるな…」と思ったらまずはお試しで触れそうな記事から見ていきましょう。
上から順番に難易度順です（個人の独断と偏見によります）。

- [【Unity】ML-Agentsで機械学習を実践する！｜Macでの環境構築と学習方法](https://xr-hub.com/archives/18825)

- [ML-Agentsを使ってみる](https://clean-copy-of-onenote.hatenablog.com/entry/uity_mlagents)

- [Windows10でUnityとML-Agentsを使った強化学習 ～自分で新しく環境を作成して学習することろまで～](https://qiita.com/2019Shun/items/d811bbd470fc9cddcc3d)

- [MacでUnity ML-Agents(v1.0)の環境構築](https://tech.morikatron.ai/entry/2020/05/08/100000)

- [Unityで体感する強化学習【ML-Agents】](https://qiita.com/KazukiKawamura/items/e1d60ba2481c9b48b0a1#ml-agents)

そして最後に[「Unityではじめる機械学習・強化学習 Unity ML-Agents実践ゲームプログラミング」](https://www.amazon.co.jp/dp/4862464181/ref=cm_sw_r_tw_dp_TC-SFbK7XREY1?_x_encoding=UTF8&psc=1 )という本があるので、がっつり触ってみたい！という人はこちらを参照すると良いかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/2a174336-ef08-1674-cb96-cb4784e78f66.png)
rails学習　8日目

##form_withについて

```
form_with @user do |f|
```
のようにlocal: trueがない場合にはAjaxを使って部分的に変更を加える設定をしているところが変化する。
逆に

```
form_with @user, local: true do |f|
```
とするとしっかりとビュー全体が再度読み込みを開始する


・undefined local variable or method `dropdown'
のようにまずメソッドでもないようなものが「メソッド定義されていません」となったら
メソッド定義は〇〇、メソッドではない定義は’〇〇’とシングルクォートがあるかで定義される

・Rspecでこういうエラーが出た

```
 Failure/Error: fill_in 'Email', with: general_user.email
     
     Capybara::ElementNotFound:
       Unable to find field "Email" that is not disabled
```
Emailというfieldがないという状態だ。この場合はlabelとfieldが紐づいているか確認する。
テストではlabelを認識してfieldに記入するのでlabelとfieldが繋がっていなければ「labelを探したのはいいけどfieldがない」ということになってしまう。紐付けるには[f.label :〇〇]この〇〇の部分がfieldのidと一致していれば良い。
flex-direction: column を使ってみる

flex-direction: column を使ってみる

↓これと同じものを作ってみる

> ![スクリーンショット 2020-11-17 23.38.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/bc45e436-50cb-53c5-9ff9-1b6e6b48bf42.png)
> https://atom.io/


## とりあえず要素を並べる

```css
.parent {
    flex-direction: column;
}
```

```react
import React from 'react';
import './AtomPage.css';

export const AtomPage = () => {
    return (
        <>
            <ul className="parent">
                <li>ATOM</li>
                <li>1.53.0</li>
                <li>macOS</li>
                <a href="">Download</a>
            </ul>
        </>
    )
}
```

![スクリーンショット 2020-11-17 23.42.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/162f2706-ddf1-b70e-fc34-56361d6a6d4e.png)


## 形を整える

```css
.parent {
    flex-direction: column;
    border-radius: 20px;
    border: 1px solid #4e4b4d;
    list-style: none;
    display: inline-flex;
    padding: 0;
    text-align: center;
    color: #efdab9;
}

.item {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 2em;
    
}

.item a {
    text-decoration: none;
    color: #efdab9;
}

.parent li+li {
    border-top: 1px solid #4e4b4d;
}

body {
    background-color: #343233;
}
```

```react
import React from 'react';
import './AtomPage.css';

export const AtomPage = () => {
    return (
        <>
            <ul className="parent">
                <li className="item">ATOM</li>
                <li className="item">1.53.0</li>
                <li className="item">macOS</li>
                <li className="item"><a href="">download</a></li>
            </ul>
        </>
    )
}
```

![スクリーンショット 2020-11-18 0.02.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/a9499eef-ac40-6c37-82a8-56d141258133.png)
【初心者でもわかる】タップしたら電話がかけられるようにする方法（レスポンシブ対応）

# どうも7noteです。タップしたら電話がかけられるようにする方法。PCは反応させないようにします。

ヘッダーやフッターなどに電話番号を掲載した際に、**タップで電話をかけられるようにする方法**です。
お問い合わせ窓口のページなどにも使いますね。

実はけっこう簡単に実装することができるのですが、**対策をしないとPCから見たときにも反応してしまう**ので、その**対策方法も合わせて実装**します。


## ソース

```index.html
<a href="tel:00012345678">000-1234-5678</a>   <!-- href属性に「tel:」と「電話番号」を記載する。 -->
```

```style.css
/* 750px以上の幅（PC等）がある時だけ */
@media screen and (min-width: 768px) {
  a[href^="tel:"] {
    pointer-events: none;  /* カーソルイベントを無効 */
  }
}
```

## 解説

**aタグのhref属性に、「tel:」と「電話番号」を書くことで動作します。**
必ずaタグでなければいけない事と、番号の前に「tel:」をつける必要性があります。
「tel:」の後の電話番号は**ハイフン(-)ありでもなしでも動作する**ので好きな方が使えます。

### スマホのみ対応にする方法

style.cssに書いているようにaタグのhref属性が「tel:」から始まるものは、`pointer-events: none;`で無効にすることができます。
`@media screen and (min-width: 768px)`の指定でPCにだけこれを無効にすることで、スマホからタップした時にだけ反応するようにできる仕組みです。

## おまけ（国際電話の場合）

```html
<a href="tel:+81-90-0000-0000">090-0000-0000</a>
```

国コードの入力が必要！！

参考：https://webliker.info/65145/



## まとめ

簡単に実装できますし、aタグなのでテキストだけでなくボタンのようなデザインを作って「お電話はこちら！」というようなボタンにすることも可能です。
PCの時に誤ってクリックできてしまうと、無駄なアラートがでるのでしっかりと無効化の処理も忘れずに入れること！

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】HTML・CSSのちょいテク詰め合わせ](https://qiita.com/7note)
missingintegers python 個人メモ

missingintegers


普通にやったらもちろんN**2で返ってくる。ので、おそらく普通のやり方らしいが、フラグを作ってそこを積算的に立てていく。と一周+最後の判別ですむ(サイズ(N)で住む)

```
def solution(A):
    A = sorted(A)
    B = [i for i in A if (0 < i) and (i <= len(A))]
    tester = [0] * len(A)
    for i in B:
        tester[i-1] +=1
    try:
        return tester.index(0) + 1
    except:
        return len(B)+1
```
mySQLコマンドまとめ

大学のデータベースの授業のノートみたいなものです。

#### 起動

```bash
$mysql.server start
$mysql -uroot
```

#### 終了

```sql
exit;
```



#### SELECT文

```sql
SELECT 列名 FROM 表 WHERE 条件;
```

全てを指定は `*`



#### COUNT関数

```sql
SELECT COUNT(*) FROM 表;
```

表の中の全ての行数を求める



#### GROUP BY句

項目ごとにグループ化

平均値の計算や集計を行う際に使用。



#### HAVING句

GROUP BYの結果に対して条件を付与する



#### ODER BY句

データを並べ替え

`ASC` で昇順，`DESC`で降順。



#### 新規データベースを作成

```sql
create databese データベース名;
```



#### データベース一覧を表示

```sql
show databases;
```



#### データベースを指定

```sql
use データベース名;
```



#### 表の作成

```sql
create table 表のタイトル(列名 データ型,… ,)
```

データ型は intやfloatなど

charの場合はchar(5)のように最大文字数を指定。



#### データの挿入

```sql
INSERT INTO 表のタイトル
(列名,…) VALUES
(データ,…);
```



#### 削除

```sql
DELETE FROM 表の名前;
```

表全部削除



```sql
DELETE FROM 表の名前 WHERE 削除する条件;
```

条件に当てはまるものを削除



#### 表の更新

```sql
UPDATE 表の名前 SET 列名=値 WHERE 行選択の条件;
```

SET のところで四則演算も可能。
ハンドトラッキングを試してみろう!

今回、mediapipeの動き方を調査して、ハンドトラッキングの仕組みについて話させていただきます。

# 伝えたいこと
+ mediapipeの概要
+ ハンドトラッキングモデルの仕組み

# mediapipeの概要
MediaPipeは、クロスプラットフォーム（デスクトップ、モバイル、ウェブ、Raspberryなどのマイコン）のマルチモーダル適用MLパイプラインを構築するためのフレームワークです。


## コンセプト
https://google.github.io/mediapipe/framework_concepts/framework_concepts.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521590/2ec7b94f-30b3-b871-5fc0-69272ca19091.png)

+ **グラフ(Graph)**：以上の画像のような**ノード**のネットワークを保持します
+ **パケット(Packet)**：基本データユニットです。パケットの中にはペイロード（テキストや画像データなど）とタイムスタンプがあります
+ **ノード(Nodes)**：インプットストリームのパケットを処理してアウトプットストリームに新しいパケットを抽出します
+ **ストリーム(Streams)**：一連のパケットを伝送する2つのノード間の接続です
+ **側パケット(Side packets)**：タイムスタンプのない単一パケット(設定値とか、静的なワンタイムインプット)

# ハンドトラッキンググラフ
試しのリンク：https://viz.mediapipe.dev/demo/hand_tracking
参考：https://webbigdata.jp/ai/post-3992
##　仕組み
![Screenshot from 2020-11-17 21-58-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521590/6785b069-1163-4446-c5a8-2985f8bc5a21.png)

ハンドトラッキンググラフ：
インプットノード(input_frames_gpu)：ウェブカメラからビデオデータ

1. インプット動画を水平方向に反転する(ImageTransformation)
2. 後ろのフローに１つ画像だけ権限をする(FlowLimiter)
3. 画像全体を操作し、手のバウンディングボックスを返す手のひら検出器モデル(HandDetectionというノード)
    + インプット：画像
    + アウトプット：手のバウンディングボックス(NORM_RECT)
4. 手のひら検出器によって定義されたトリミングされた画像領域で動作し、忠実度の高い3D手のキーポイントを返す手のランドマークモデル(HandLandmarkというノード)。
    + インプットは
        + 画像(IMAGE)
        + 手があるバウンディングボックス(NORM_RECT)
    + アウトプットは
        + 手の21位置(LANDMARKS)
        + 右手か左手か（HANDEDNESS）
        + 現時点の手のバウンディングボックス(NORM_RECT)
        + そのハウンディングボックスにある手があるかどうか(PRESENCE)





一旦今回ここまでです。次、ハンドトラッキンググラフのコードを編集してみて簡単なことをやりましょう！