OmniAICreator/Qiita-1.07M huggingface dataset:
/etc/hosts内のIPアドレス変更により、参照するDBが切り替わるか検証

---前回までのあらすじ---
AWS_WEB3層環境構築①
https://qiita.com/shinichi_yoshioka/items/7226b9ebaad06c569c80
AWS_WEB3層環境構築②
https://qiita.com/shinichi_yoshioka/items/e358f57a3ecb7735c091
AWS_WEB3層環境構築③
https://qiita.com/shinichi_yoshioka/items/5253fd442376c6f222b2

![絵_v5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/2c3022dd-ed7e-b439-bfef-ab2b07a439d6.png)

今回やりたいことは以下です。
1.DBサーバ②の構築
2.APサーバからのDB参照をIPアドレスから名前に変更(/etc/hostsおよびJSPファイルの編集)
3.APサーバの/etc/hosts内のIPアドレスをDBサーバ①からDBサーバ②に変更することで、参照するDBが変わるかを確認

◆DBサーバ②の構築
前に作ったDBサーバ①のAMIイメージを作成し、そのイメージからDBサーバ②を構築する。

まずは、イメージ元のDBサーバ①を停止する。
停止するインスタンスを選択して、[インスタンスの状態]-[インスタンスの停止]
![AMI作成1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/1938b6cc-a5ec-facf-f7c4-64b44a082315.png)
次に、イメージ元のインスタンスを選択して、[イメージとテンプレート]-[イメージを作成]
![AMI作成2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/9c3adae0-4d7b-d3a9-55a5-57c028a4eff2.png)
適当に名前をつけて、[イメージを作成]
![AMI作成3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/4352e29c-a76d-7ce4-be7e-1e36b2263ea4.png)
EBSやその他設定は割愛するが、セキュリティグループの作成はDBサーバ①に適用しているセキュリティグループを適用した。
![AMI作成4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/d657ce49-e994-21a1-9fdb-fd529cfb0225.png)
AMIから起動すれば、DBサーバ②の完成。まじ楽なんだがｗ

◆APサーバの/etc/hostsに名前を定義
対象:APサーバ
/etc/hostsに以下1行を追加した。

```
vi /etc/hosts
172.16.3.6 TEST-DB
```
![hostsの変更.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/c4f46bb3-0c17-0556-213b-a6e6c68afdb5.png)

次にJSPファイルを編集

```
cd /opt/tomcat/webapps/jsp
vi test.jsp
```
jdbc:mysql://172.16.3.6:3306/world →　jdbc:mysql://TEST-DB:3306/world
![20210128_1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/b23a590a-28f8-d78b-34bd-e359e84bbdeb.png)

編集後、ブラウザにWEBサーバのパブリックアドレスを入力し、「名前」でも問題なくDBサーバ①を参照していることを確認した。
![20210128_3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/0965c012-8017-1aca-ede1-2f66bdb7d418.png)

ここで/etc/hostsのIPアドレスをDBサーバ①からDBサーバ②のIPアドレス(プライベート)に変更する。
172.16.3.6(DBサーバ①)→172.16.3.101(DBサーバ②)
![hostsの変更2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/dd616222-ae87-23c3-b7b0-f3aa49236533.png)

変更後に正常にDB参照できることを確認したうえで、
DBサーバ②のインスタンスを停止したところ、DB参照できなくなったので
問題なくDBサーバ②を参照していることが確認できた。
![20210128_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/c6f77480-21b1-c645-f938-bb0bd609f052.png)

最後に、前回までプライベートサブネットがガバガバだったので封鎖した。
プライベートサブネット用の[ルートテーブル]から、0.0.0.0/0　ターゲット:Internet-GWを削除。
![封鎖1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/38d37096-6fcc-0ff8-7f1f-e47e9846c81c.png)
APサーバに適用されているセキュリティグループは、ソースがWEBサーバのみでポート番号も8080のみに変更。
![封鎖2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/a6889319-6920-d277-7a6f-07f50b7d8335.png)
DBサーバに適用されているセキュリティグループは、ソースがAPサーバのみでポート番号も3306のみに変更。
![封鎖3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/881bbb39-c411-1e4a-8a48-53db994aea35.png)
一時的に付与していたパブリックIPアドレスも解放して、WEBサーバのみとした。
![封鎖4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032344/84a558b9-830b-8ad5-51c7-5e8ea8f795db.png)
Djangoのforms.ModelFormでフォームの初期値を設定する

## 環境
- Django 3.0.3

## init関数で初期値を設定
`fields`で登録したfieldに対して`def __init__()`内で初期値を入れます。

```
class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ('title', 'price' )

    # フィールドを初期化
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super(ProductForm, self).__init__(*args, **kwargs)
        self.fields['price'].initial = 1000

```

テンプレートビューを使っていても`forms.ModelForm`で初期値を設定すれば、フォームに初期値を入れることができます。

```
from django.views import generic
from apps.products.forms import ProductForm


class ProductCreateView(generic.CreateView):
    """ 新規登録 """
    model = Product
    form_class = ProductForm
    template_name = "products/add.html"
    raise_exception = True # 403ページの表示


class ProductUpdateView(generic.UpdateView):
    """ 更新 """
    model = Product
    form_class = ProductForm
    template_name = 'products/edit.html'
    raise_exception = True
    pk_url_kwarg = "id"
    success_url = reverse_lazy('products:index')

```
AWSを触って出てきた用語まとめ

# はじめに
AWSを勉強し始めてでてきた用語が覚えられないので、まとめてみました。

# AWS IAM
IAMとはAWSの操作をよりセキュアに行うための認証の認可を管理するためのサービスのことです。
認証：本人性の確認（Aさんですか？）
認可：リソースに対する利用権限の付与（Aさんはサーバーを起動できるが、削除できない）

## IAMに関連する用語

- IAMポリシー  
AWSのアクセス権限のリストを指します。IAMユーザーやIAMグループにはデフォルトのアクセス許可がないため、IAMポリシーでアクセス許可を設定し、ポリシーを割り当てる必要があります。
- IAMユーザー  
AWSで作成するユーザーまたはアプリケーションのこと。基本的に人に対して使われます。
- IAMグループ  
IAMユーザーをまとめる（部署など）グループのこと。IAMロールを所属させることはできません。IAMグループに関連付けられたポリシーはIAMユーザーに引き継がれます。
- IAMロール  
ユーザーやグループではなく、EC2などのAWSのサービスや他のアカウントに対してにAWS の操作権限を付与するための仕組みです。例えば、IAMロールを使用してAWSのサービスに一時的にデータへのセキュリティ認証情報を渡すことでデータとAWSサービスとのやり取りができるようになります。ハッキングされた場合でもロールを停止させればアクセスを止められます。IAMユーザーがもつアクセスキーを埋め込んで直接アクセスするということもできますが、それは非推奨です。
- ルートユーザー  
AWSのリソース・サービスすべてに完全なアクセス権を持つユーザーのことを指します。
メールアドレスとパスワードでサインインするとルートユーザーとして作業できますが、権限が強すぎるので極力ルートユーザーを使わないようにしたほうがいいです。AWSアカウントの解約などルートユーザーでないとできないこともあります。

# AmazonVPC（VietualPrivateCloud）
AmazonVPCとはユーザー専用のプライベートなクラウド環境を提供するサービスのことです。外部に公開することも可能です。
VPCにEC2といった仮想マシンやRDSなどのデータベースを立てることができます。

## VPCに関連する用語

- リージョン  
地理的に大きく離れたデータセンターの集合体をリージョンと呼びます。
- アベイラビリティゾーン（AZ）  
リージョンをさらに小さくした区分のことを指します。AZを跨いで障害が起こらないようになっています。  
- サブネット  
VPCを区切りたいときにサブネットを使用します。リージョンやAZは物理的に区切られていますが、サブネットは論理的に区切られています。一つのサブネットは一つのAZに作られます。AZを跨いでサブネットを作成することはできません。  
例えば、データベースサーバーをインターネットからアクセスさせないようにし、Webサーバーはインターネットに公開したい場合、サブネットを一つのAZで2つに分けることで、サブネットごとに公開の制御ができます。インターネットからのアクセスを受け付けるのはパブリックサブネット、受け付けないのはプライベートサブネットと呼びます。
- セキュリティグループ
VPC内のインスタンス（サーバー）のトラフィックを制限するファイアウォール機能を指します。デフォルトは全部しまっています。
- ネットワークACL  
サブネット単位でしていできるファイアウォール機能を指します。
- NATゲートウェイ  
プライベートサブネットにあるインスタンスがインターネットにアクセスする場合に必要となるゲートウェイを指します。同じAZ内のパブリックサブネットにNATゲートウェイを立ててそこを介してプライベートサブネットとインターネットのアクセスを行うようです。
- ルートテーブル  
サブネット内にあるインスタンス等がどこに通信にいくかのルールを定めたものです。IPアドレスを見て、どこに通信をさせるかが書かれている表です。表にない宛先には通信できません。
- CIDR(読み：サイダー)  
一つのVPCには一つのCIDR（ネットワークアドレス10.0.0.0/16のようなもの）を定義します。サブネットにはVPCより小さいCIDRを割り当てます。プライベートサブネット、およびパブリックサブネットのアウトバンドトラフィックにVPCのCIDRを指定すると、お互いのサブネットにアクセスできる。
- インバウンドトラフィック・アウトバンドトラフィック  
インバウンドは外部からのアクセス、アウトバンドは外部へのアクセスのことを指します。


## Amazon EC2(Elastic Compute Cloud)
１時間または秒単位で課金される仮想サーバーのことです。起動している間は支払いが発生します。

## EC2に関連する用語
- インスタンスタイプ
仮想サーバーのマシンスペック（CPUやメモリの性能など）のことを指します。
- 「c5n.xlarge」というインスタンスタイプでは
 + c:インスタンスファミリー(バースト可能であったり、ストレージ可能であったり、用途によって様々なインスタンスファミリーを選べる)
 + 5:インスタンス世代（最新を選ぶ）
 + xlarge：インスタンスサイズ（メモリ・CPUが増える）



# さいごに
VPCのあたりが特に複雑でいつも忘れてしまいます。今回まとめたことによってだいぶ頭が整理されました
特にVPCについて以下が参考になりました。
https://d1.awsstatic.com/webinars/jp/pdf/services/20201021_AWS-BlackBelt-VPC.pdf
MySQL 関数・句


##はじめに
MySQLの「関数」や「句」について、忘れていたので抜粋してまとめています（自分メモ）。

MySQL：Ver 8.0.23

##BETWEEN句

【使用例】 ageカラムの値が10以上20以下のデータを取得

```
SELECT * FROM member WHERE age between 10 AND 20 ;
```
##IN句
複数の一致するかの条件判定をまとめて行うために使用する命令。IN句を使わない場合と比較して、条件文を短く済ませることができる。

`OR`を使って複数の指定をする場合

```
SELECT * FROM fruit WHERE name ="apple" OR name ="orange" ;
```

`IN`句を使って複数の指定をする場合

```
SELECT * FROM fruit WHERE name IN('apple','orange');
```

##DISTINCT句

検索するカラム名の重複レコードを一つにまとめて表示する。

```
SELECT DISTINCT col_name FROM table_name ;
```

重複するデータを表示しないようにするためにはDISTINCT句を使用する方法とグループ化を使用する方法の2種類がある。


##DATE_FORMAT関数

日付を「2021年01月28日」のように表示する。表示の指示をしない場合は「2020-01-28」。

```
SELECT DATE_FORMTA(日付,変換フォーマット);
```

【使用例】 memberテーブルの中から、nameとbirthを取得する。birthはフォーマットを変更。

```
SELECT name, DATE_FORMAT(birth,'%Y年%m月%d日') from members ;
```

###その他の変換フォーマット

- %Y = 4桁の年(2021)
- %y = 2桁の年(21)
- %M = 英語の月名(JULY)
- %m = ２桁の月(07)
- %d = 2桁の日付
- %k = 24時間表記の時間
- %i = 2桁の分
- %s = 2桁の秒

##IFNULL関数

【使用例】 nameカラムに格納されている値がNULLの場合、NoNameを返す。

```
SELECT id, IFNULL(name,'NoName') FROM member;
```


※ カラム名が`IFNULL(name,'NoName')` となってしまうため、
下記のように`AS`で名前を戻すのも良い。

```
SELECT id, INFULL(name,'NoName') AS name FROM member;
```

##COUNT関数

【使用例】 memberテーブルのpointが60以上80未満の人数を合計する。

```
SELECT COUNT(id) AS 'カウント数' FROM member WHERE point >= 60 AND point < 80 ;
```

下記のようにアスタリスクでも表示可能だが、データ数が増えるため遅くなる。PK（プライマリーキー）等で示すのがベスト。

```
SELECT COUNT(*) AS 'カウント数' FROM member WHERE point >= 60 AND point < 80 ;
```

##最後に
次回は結合についてまとめます。
（もしこの記事に誤りがありましたらご教授いただけると幸いです。）
ドリコム 19新卒が 「ADDMe Tech #001 もう一度就活するならどの会社受ける？」 に登壇しました！

![eyecatch_2101ADDMeTech.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218415/cc9b9bc9-440f-d870-5aee-5ca826f2ba5e.png)

※ 本稿は [Tech Inside Drecom](https://tech.drecom.co.jp/?_src=qiita) に掲載された記事、「[ドリコム 19新卒が 「ADDMe Tech #001 もう一度就活するならどの会社受ける？」 に登壇しました！](https://tech.drecom.co.jp/addme-tech-dec-2020/?_src=qiita)」の Qiita 出張版です。

---

19新卒クライアントサイドエンジニアの古川です。
本記事は2020/12/03(木)に開催された
「[【もう一度就活するなら】ADDMe Tech #001 【どのゲーム会社受ける？】](https://addme.connpass.com/event/194206/)」のイベント登壇レポート記事です。 前回の記事は「[https://tech.drecom.co.jp/addme-tech-oct-2020/](https://tech.drecom.co.jp/addme-tech-oct-2020/?_src=qiita)」です。

# ADDMe Techとは?

“ADDMe”とは、
「アカツキ（A）」「ドリコム（D）」「Donuts（D）」「ミクシィ（M）」 (敬称略)
4社の「エンジニア（e）」が
毎回変わるトークテーマに沿ってぶっちゃけトークをするオンラインLIVEイベントです。

# 当時どういう会社を受けたか

私の場合は初めからゲーム業界に絞っていて、結局本選考はドリコムだけでインターンは色々な会社を受けていました。 他の方は特にゲーム業界に絞っていたわけではなく、「自分が楽しめること」を軸に企業選びをしていたのが驚きでした。 また、企業選びに関する気になった質問で「好きなIP or 社風」のどちらで選べば良いかというものがあり…難しい問題でもあるため皆悩んだ挙句「社風・理念」を重視する（していた）ことでほぼ一致しました。 個人の見解としては、（モチベーションも大切ですが）自分に合わない環境で仕事を続けて、せっかくの好きなIPを嫌いになってしまうといった最悪の事態だけは避けるべきかなと思っています…

# 今もう一回就活するならどの会社を受ける？

もともとコンシューマーしか考えていなかったのと、好きなゲームが「DQ, FF, KH」なのもあるので私はあの会社と答えました…。 もちろんコンシューマーからスマホに変わった理由を聞かれたので、就活を進めていく中で「色々と経験・挑戦できる」「ユーザーからのレスポンスの速さ」の部分を重視するようになったことを伝えました。

# 面接官になって改めて気づいたこと

私はまだ面接官をしたことがないので聞くだけでしたが、他の方によると「逆質問」「制作物のこだわり」に関して重視するようになったみたいです。特に制作物に関しては、担当した箇所が分かりやすくなっていると評価の判断をしやすいといった意見がありました。もし今後面接官を担当する機会があれば是非参考にしようと思います！

# オススメの一冊

私は入社前に読んだ「ゲームを動かす技術と発想」を選びました。学生の頃は主にUnityなどのゲームエンジンを用いて（頼って）コンテンツ制作をしていたこともあり、正直どういった仕組み・流れでゲームが動いているか理解していませんでした…描画周りでいうと、UnityをインストールしてUnityちゃんをドラッグすれば3Dモデルが表示されますが、ちゃんと描画ライブラリ等用いて3Dモデルを表示するとなるとこんなに大変なんだ！といった驚きが強かったのが主な理由です。他の方は「ソフトウェア開発」や「セキュリティ」などに関する本を紹介していました。（どれも読んだことがなかったです）

# 感想

トークが始まるまでは少なからず抵抗もありとても緊張していましたが、いざ始まると就活していた頃を思い出しながら新鮮な気持ちで和気あいあいと過ごすことができました！1時間半はあっという間でとても楽しかったです。まだ入社して2年も経ってないですが、このイベントのおかげで初心にかえれた部分もあるので登壇してよかったです！（ずっとヘラヘラしててすみません）

---

Tech Inside Drecom の最新の情報は Facebook や Twitter からお届けしています、フォローよろしくおねがいします！

Twitter: [@DRECOM_TECH](https://twitter.com/DRECOM_TECH)
Facebook: [tech.inside.drecom](https://www.facebook.com/tech.inside.drecom)

---

※ その他の Tech Inside Drecom の記事は、[コチラ](https://tech.drecom.co.jp/?_src=qiita)からお探しいただけます！
AjaxのPOSTでデータを送信しようとしてうまくいかないとき

大参考にさせていただきました
[ajaxのPOST送信で403が返却される場合の対処方法](https://qiita.com/teradatk/items/e112dc39188a380d24d9)

###環境

spring boot
**spring security**
thymeleaf

###SpringSecurityを使っているときはCSRFトークンが必要
SpringSecurityを使ってログイン機能を作った場合、そのアプリケーション全体でCSRF対策が有効になる

すごくシンプルに言うと、

`POSTメソッドを使うときは、入力データだけじゃなくてCSRFトークンも送らないとアクセス禁止になる！`

###th:actionでトークンが自動で挿入される

 [参考](https://macchinetta.github.io/server-guideline-thymeleaf/current/ja/Security/CSRF.html#hidden)

Ajaxじゃなくて普通にformで画面遷移する場合は、

```html
<form th:action="@{hoge}" method="post">

</form>
```

のように書けば

```html
<form action="/login" method="post">
    <!-- Spring MVCの機能と連携して出力されたCSRFトークン値のhidden項目 -->
    <input type="hidden"
        name="_csrf" value="63845086-6b57-4261-8440-97a3c6fa6b99" />
    <!-- omitted -->
</form>

```

超便利！！

###でもAjaxのときは自動で生成されず、Forbiddenが返ってくる

chromeのデベロッパーツールでヘッダーを確認してみると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/cd707f90-9724-c648-9105-07b498658a9b.png)

403のステータスコード。アクセスしたらアカンって言われてる。

俺がええって言うてんのに！

SpringSecurityが勝手に「だってCSRFトークンないからあきまへん」って頑なになっとるんですな。


###CSRFトークンを手動でAjaxのヘッダーにセットする

```html

// htmlファイルの最後にCSRFをセット
// ちょっと変な場所
</body>
<meta th:name="_csrf" th:content="${_csrf.token}"/>
<meta th:name="_csrf_header" th:content="${_csrf.headerName}"/>
</html>
```

##### `</body>`の直前だとエラーになります。
ちょっと変な場所だけど、ここじゃないとダメでした

##### `<head>`の中に書いても読み込まれません

テンプレートエンジンを利用している場合、layoutファイルに次の様な書いてある場合は、個別のhtmlファイルにmetaを挿入しても読み込まれない

```html
<head xmlns:th="http://www.thymeleaf.org"
	th:fragment="base_header(title, scripts, links)">


```

`base_header(title, scripts, links)`
この部分で、個別のファイルで`<head>`の中に書いてある
title
script
link
は読み込めるようになっている

が

metaはない → headにmetaを追加してもCSRFトークンはセットできない


###postで403が返ってきたらCSRFトークンが送信できているか確認しよう！

これほんと初歩でしょうけど。

これで丸一日かかってしまいました。。。
AWS - C9でLaravel / Nuxt.jsを構築する備忘録

毎回調べるのが面倒なので、未来の自分へ備忘録です。
順番に実行したら構築出来るわけではありません。

**今回構成する内容**
・バックエンド：laravel 6系
・フロントエンド：vue.js nuxt.js vuetify

### composerのインストール
```
brew install composer
```
終わったら念のため-vでバージョン確認。


### laravelのインストール
```
composer create-project --prefer-dist laravel/laravel app_name "6.*"
```
このコマンドでは何故かvenderファイル、envファイルが作成されなかった。



### インストールされているphpパッケージのバージョン確認
```
yum list installed | grep php
```


### このコマンドで確認出来た古いパッケージの削除
```
sudo yum erase -y hogehoge
```

補足：-yは全ての問い合わせに対してYESで返す。


### yumのアップグレード
```
sudo yum upgrade
sudo yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
```



### パッケージインストール
```
sudo yum install -y php73 php73-php-pdo php73-php-mbstring php73-php-xml
```
補足：確かlaravelは確か7.3以降のphpが必要なはず

### PHPコマンドを使えるようにする
```
$which php73
/usr/bin/php73
$alias php='/usr/bin/php73'
```
補足：whichコマンドでどこにファイルがあるのか調べる。その後aliasコマンドでphpと入力したときの呼び出し先を設定する。


### composerコマンドを使えるようにする
```
sudo ln -s /usr/bin/php73 /usr/bin/php
```

### migrationが動かない場合
```
sudo yum update -y
```
とりあえずyumをアップデートする

### mysqlを使えるようにする
```
sudo yum install --disablerepo=* --enablerepo=epel,remi,remi-safe,remi-php73 php-mysqlnd
php -m | grep pdo
```
mysqlndは最初から入っていないのでインストール、確認する
Cassandra立ち上げコマンドなど

Cassandraのコマンドを備忘録として残します

```
//ローカルのCassandra立ち上げる
 % cassangra -f

//Cassandraのなかに入る
 % cqlsh

//テーブル一覧みる
 % describe tales

// cassandra のコンテナIDを調べる
 % docker ps
 % docker exec -it container_id cqlsh
sudoさん危機！

Sudo Security Issue (CVE-2021-3156)
sudoの脆弱性情報(Important: CVE-2021-3156: Baron Samedi)

とりあえず、sudoは退避かリネーム。

Systems Manager Patch Manager で特定パッチを適用する
https://dev.classmethod.jp/articles/apply-specified-patch-by-ssm-patch-manager/
slick+lightboxのモーダルでかっこいいパターン表示を作るまで

既にslick実装済みの環境に､モーダルを追加して､なにかのレイアウトとかデザインをかっこよく数パターン表示できるようにした際のまとめ｡

##モーダルって何？

以下がわかりやすいですかね｡クリックするとその画像だけの別ページが最前面に表示されてくれるイメージ｡
https://goworkship.com/magazine/modal-windows-mobileui/

##手順

###wordpress環境だけど､プラグイン使わずにlightbox実装したい｡
重くなっちゃうので､なるべくプラグインは使わない思想のもと｡
lightboxはめちゃくちゃお手軽で簡単なので､以下の記事を参考に実装｡
ぐぐるといくつか出てきますが､これが一番わかりやすかったです｡
https://www.axisjp.co.jp/news/1247

lightboxは以下からDLですね.
https://github.com/lokesh/lightbox2/releases

で､上記参考ページのとおりに実装したんだけど､
**slickを当初横スライドにしていたはずなのに､縦並びになってしまう・・・｡**

モーダルがなにか悪さしてるんでしょう｡
ぐぐる｡

### jsの読み込みタイミングがポイント

slickとlightbox-plus-jquery.min.jsをどちらもfooter.phpで読むこむように指定していたけども､
jsの読み込み順序で､縦並びになっちゃったり上手く作用してくれないことがあるらしい｡
jsが干渉する､干渉してしまう､っていうのはこういうことなんだな｡学び｡

http://creatornote.nakweb.com/%E3%80%90%E8%A7%A3%E6%B1%BA%E3%80%91slick%E3%81%A7%E3%81%AA%E3%81%9C%E3%81%8B%E7%B8%A6%E3%81%AA%E3%82%89%E3%81%B3%E3%81%AE%E3%81%BE%E3%81%BE%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%81%99%E3%82%8B/
JSON について メモ

## そもそもJSONって何の略？
JSONは**"JavaScript Object Notation"**の略で、
直訳すると**「JavaScriptオブジェクト記法」**。
...まだ、あんまりイメージが湧かないので、
更に意訳も入れてもう少しかみ砕いてみた。
↓
**JSONは「JavaScriptのオブジェクトの書き方を元にしたデータ定義方法」**
こんな感じだろうか。

## JSONとは？
とりあえず、何の略なのか調べて、日本語訳もしてみたけど、
具体的に何なの？とまだ頭の中がクエスチョンマークの為、もう少し調べてみよう。

Wikiには、↓のように書いてあった。

*JavaScript Object Notation（JSON、ジェイソン）はデータ記述言語の1つである。軽量なテキストベースのデータ交換用フォーマットでありプログラミング言語を問わず利用できる。名称と構文はJavaScriptにおけるオブジェクトの表記法に由来する。*

(引用元: [Wikipedia](https://ja.wikipedia.org/wiki/JavaScript_Object_Notation), 2021/01/28)

この文章を見ると、何となくJSONがデータのやり取りをする為の言語(フォーマット)だというのが分かる。
では実際に、どのように、どのようなデータをやり取りするのか。
筆者なりに、実際にシステム開発に携わったことがない人にもわかるように、
分かりやすくまとめてみる。

例えば、あるWebサイトに登録しているユーザがログインするとする。
まずログインする為には、画面からユーザ固有のユーザIDとパスワードなどが必要である。
それで画面から、

**ユーザID: hogehoge@sample.com**
**PASSWORD: testtest**

などど入力してログインボタンを押してみる。

すると、画面側からデータの管理しているところへ「このユーザ、いる？」と確認するために、
確認したいユーザのデータ(この話で言うと、ユーザIDとPASSWORD)を送ることになる。
その送るときのデータの書き方がいくつかあるのだけど、その中の一つがJSONということ。

それで、実際どのような形で送るのかというと、
最初にも書いた通り、JavaScriptのオブジェクト型に似た形式で送る。

例えば、↓みたいな感じ。

```JSON
{
  "user_id": "hogehoge@sample.com",
  "password": "testtest"
}
```
この書き方では、{ } (中括弧)でひとまとまりのデータを表していて、
上の例で考えると、**"1ユーザがログインする為に必要なひとまとまりの情報"**と
認識してもらえればいい。

ひとまとまりのデータなので、この設定はこの値、あの設定はあの値という風に書けるのが特徴。
例でも、ユーザIDは "user_id": "hogehoge@sample.com"、パスワードは "password": "testtest"と
書いてまとめておくことが可能。

それで前に書いた内容に戻って、本来これは元々JavaScriptで扱うオブジェクトの書き方を真似てるって話だが、
↓ がJavaScriptで同じデータをオブジェクト型で表現したときの書き方。

```JS
var user_login = {
  user_id: "hogehoge@sample.com",
  password: "testtest"
}
```

上の例ではJavaScriptの変数というものを使っていて、
変数であるuser_loginに、JavaScriptのオブジェクト型のデータを代入している。

これを見ると、JSONとJavaScriptのオブジェクトの書き方はほとんど同じであることが分かる。
しいて言うのであれば、user_idとかpasswordとかの項目名の部分に""(ダブルクォーテーション)が付いていないだけ。

だから、本当にJSONはJavaScriptのオブジェクトの書き方をほぼ丸パクしているのが分かる。

### まとめ

そんなこんなで、ここまでJSONのことを簡単に触れてきたけど、
最後にもう一度簡単にまとめると、

JSONとは...

**何らかのデータのやり取りをするときに使う、
データを渡すためのフォーマット(書き方)の一つで、
それはJavaScriptをほとんど真似して作られた**

ってこと。

### あとがき

今回、自分の中での整理も含めて、初めてQiitaに投稿する記事として書いてみた。
何か読んでみて個々の書き方わかりづらいとか、そういうコメント等があれば、
是非今後のご参考までに遠慮せず教えて下さい。
最後まで読んでくれてありがとう。
【UI/UXデザイン】UI/UXデザインに関するメモ<1/28作成中>

# UI/UXデザイン

## 良いUIデザイン
:white_check_mark: 可視性が高い
:white_check_mark: クリックしやすい
:white_check_mark: クリッカブルの認識性が高い
:white_check_mark: 機能が認識しやすい
:white_check_mark: 情報理解がしやすい
:white_check_mark: ユーザが必要な情報にたどり着きやすい
:white_check_mark: フォーム入力が容易

:apple: [Apple公式のデザインガイドライン](https://developer.apple.com/design/human-interface-guidelines/)

## 悪いUIデザイン
:x: 余白がない
 … アイコンは全体の2/3
:x: 全てのパーツが同じサイズ
 … 情報の優先順位
:x: 色が多い
 … 1画面に4色以内

## 配色
色相 … 色の種類
彩度 … 色の鮮やかさ
明度 … 色の明るさ

### 配色パターン
1色(彩度あり) + 無彩色(彩度0の「白 - 黒」)
補色(配色比率は7:3)
3色の場合は6:3:1(カラーパレットで三角形を作る)
4色以上の場合は(カラーパレットでn角形を作る, 彩度は固定 or 1色だけ彩度高め)
 :arrow_right: [Adobe Color](https://color.adobe.com)で配色を決定するのもアリ

## インタラクションコストの概念

### インタラクションコストとは
「アクション ⇄ リアクション」のコスト

(例)
アクション: メニューをタップ
リアクション: メニューが表示

(その他の例)
- フォームに合わせたキーボード選択
- バリデーションの即時表示(正誤がすぐに確認できる)
- 冗長なページの回避(ページの要約)
- サジェスト機能
- 類似商品やおすすめの最適化

## UXデザイン
:white_check_mark: どんな体験 / 価値観を与えるか
:white_check_mark: 世界観の創出

## デザイン
:white_check_mark: グルーピング
 … 類似性の高いものはカテゴライズ
:white_check_mark: デザインの一貫性
 … 余白や配色のメリハリ
:white_check_mark: 機能の連想
 … 「アイコン × 文字」の組み合わせ
bulletml.jsの研究 その10

#概要

bulletml.jsの研究です。
技を調査。

#ワインダー

```
<bulletml>
	<action label="top">
		<repeat>
			<times>10</times>
			<action>
				<fire>
					<direction type="absolute">2</direction>
					<bulletRef label="winderBullet"/>
				</fire>
				<actionRef label="winderSequence">
					<param>31</param>
				</actionRef>
				<wait>200</wait>
			</action>			
		</repeat>
	</action>
	<bullet label="winderBullet">
		<speed>3</speed>
	</bullet>
	<fire label="fireWinder">
		<direction type="sequence">$1</direction>
		<bulletRef label="winderBullet"/>
	</fire>
	<action label="roundWinder">
		<fireRef label="fireWinder">
			<param>$1</param>
		</fireRef>
		<repeat> 
			<times>11</times>
			<action>
				<fireRef label="fireWinder">
					<param>30</param>
				</fireRef>
			</action>
		</repeat>
		<wait>5</wait>
	</action>
	<action label="winderSequence">
		<repeat> 
			<times>12</times>
			<actionRef label="roundWinder">
				<param>30</param>
			</actionRef>
		</repeat>
		<repeat> 
			<times>12</times>
			<actionRef label="roundWinder">
				<param>$1</param>
			</actionRef>
		</repeat>
		<repeat> 
			<times>12</times>
			<actionRef label="roundWinder">
				<param>30</param>
			</actionRef>
		</repeat>
	</action>
</bulletml>

```

間隔の短い高速弾で「弾の壁」を作り、自機の動きを制限することを目的とした攻撃です。
ワインダー自体を徐々に動かす、幅を狭める等で変化をつけることが出来ます。
固定方向弾と同じく単独では意味をなさないため、他の攻撃と組み合わせて使います。

#成果物

https://embed.plnkr.co/plunk/U5n4NxPuZpYvvovb

以上。
PMI-ACPを取得しました

2021年1月にPMI-ACP試験に合格しました。
個人的な記録を残します。
正式な情報は公式サイトhttps://www.pmi.org/certifications/agile-acp をご参照ください。

#受験について

####受験場所
コロナ対策で自宅でも受験できたようですが、家族との兼ね合いで自宅受験は難しかったです。
そのため、テストセンターでの受験を選びました。

####受験申請
監査には引っかからず、申請から2営業日で申請通過しました。
メールでの連絡はなく、自分でPMIの申請ポータルをチェックしました。

####受験料
自分はPMI非会員なのでUSD 495。
PMI会員だとUSD 435。

####試験問題

* 多肢選択方式120問
* 3時間

私は90分ぐらいで終われました。見直しても分からないものは分からない（知らない）ので、あきらめて即終了。

#勉強方法

####期間
受験対策の勉強：　1か月間ぐらい？週末や業務後にコツコツやりました。

####教材
Udemyの以下のコース

* PMI-ACP Exam Prep for PMBOK 6(https://www.udemy.com/share/101WfC/) 動画の講義
* PMI-ACP Practice Exams - PMBOK6(https://www.udemy.com/share/101ZGc/) 問題集（模擬試験）

一通り講義を聞いて、試験を2回通しました。

####その他
受験目的ではないですが、役に立ったもの

* Agile（主にScrum）の座学とハンズオン：約20時間 


#####間接的に役に立ったような気がするものたち

* TDDを試してみる http://cyber-dojo.org/
* AWSでCI/CDを利用したちょっとした開発
* マイクロサービスアーキテクチャの理解


#FAQ
####なんで受験したの？
Agileの知識があることを第三者により客観的な方法で証明したかったから。

####なんで今なの？
ちょうどAgileを（PMI-ACPの試験勉強ではなく）勉強する機会があったので、記憶が新しいうちにスナップショットを取っておこうかと。
メモリ容量が少ない人間なので、追い出さないと新しいものが入っていかない。

####試験料高くない？
安くはないね。でも安くして有象無象が増えるのも資格の質を落とすよね。

####試験料はペイすると思う？
どうだろう。。今後のキャリア次第？
5万出すならシミ取りでもしたほうが良かったかも。iPadを買い替えるのでもよかったかな。と思わないでもない。
ちなみに会社から補助の類は全くない。

####認定スクラムマスターでもよかったんじゃ？
認定スクラムマスターは研修+試験が更に高額だった。。20万くらい？

####PMP持ってる？
持ってる。

####PMI-ACPを受験するのにPMPの知識はいる？
必須ではないと思います。私の周りでは、PMPの積み上げでPMI-ACPを受ける人が多い印象です。（たぶんPMPを持っていない人は認定スクラムマスターなどを取っているのでは？）
上に挙げたUdemyの講座ではPMPで勉強した内容も含まれていました。

####実務経験はある？
勤め先ははScaledAgileを導入している。スクラムマスターやアジャイルコーチはやったことがない。

####英語で勉強するの辛くない？
事前に日本語で知識を入れておけば、個人的には辛くない。そもそも用語にカタカナ多いし。
この手の試験にありがちな「変な日本語訳」（日本語で受験しても元の英語を読める）に対応する必要もあるし。
ただ、日本語の専門用語（英語から訳語ができているもの、日本語発の用語）は英語だけで覚えてしまうとややこしくなる気もする。例えば狩野モデルとか。

####受けてよかった？
今の時点では何とも。勉強は基礎固めになったので、試験勉強はしてよかったと思う。なんちゃってアジャイルに騙されたくないし。。

####Udemyの講座は試験の役に立った？
上記講座の「お客様の声」のうち、高評価のものと低評価のものを読んでみるといいと思います。

####試験は難しかった？
この手の試験には向き不向きに個人差があるから容易なことは言えない。そもそも長時間座っているのがつらい人もいるし。

####どんな問題が出た？
答えられません。
bulletml.jsの研究 その9

#概要

bulletml.jsの研究です。
技を調査。

#ウィップ

```
<bulletml>
	<action label="top">
		<repeat>
			<times>22</times>
			<action>
 				<fire>
  				<direction type="aim">0</direction>
	  			<bullet>
						<action>
 							<changeDirection>
  							<direction type="aim">0</direction>
  							<term>0</term>
 							</changeDirection>
						</action>
					</bullet>
 				</fire>
				<repeat>
					<times>5</times>
					<action>
 						<fire>
  						<direction type="aim">0</direction>
							<speed>1.5</speed>
	  					<bullet>
								<action>
 									<changeDirection>
  									<direction type="aim">0</direction>
  									<term>0</term>
 									</changeDirection>
								</action>
							</bullet>
 						</fire>
 						<wait>10</wait>
					</action>
				</repeat> 
 				<wait>200</wait>
			</action>
		</repeat>
	</action>
</bulletml>

```

回転砲台が発射方向を変化させていく攻撃だとするならば、こちらは発射速度を変化させていく攻撃です。
先に撃った遅い弾を、後から撃つ速い弾が追い越して行きます。
プレイヤーにとっては、遅い弾がガイドになってくれるため、単発で発射されたのではとても避けられないような速い弾でも回避できる攻撃となります。
発射間隔や発射方向を変化させることでバリエーションを広げることができます。

#成果物

https://embed.plnkr.co/plunk/PMvGKalEZBFcwQuo


以上。
選択済みのラジオボタンを再度押して解除できるようにする

選択済みのラジオボタンに対して、チェックボックスのように再度押すことで解除できるようにするJavaScriptのサンプル。
複数グループにも対応。

[**動作デモ**](https://akebi.jp/temp/radiobutton_release_test.html)

```html:test.html
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='utf-8'>
<title>ラジオボタン 解除対応サンプル</title>
</head>
<body>
groupA:
<label><input type='radio' name='groupA' value='1'>1</label>
<label><input type='radio' name='groupA' value='2'>2</label>
<label><input type='radio' name='groupA' value='3'>3</label>
<br>

groupB:
<label><input type='radio' name='groupB' value='1'>1</label>
<label><input type='radio' name='groupB' value='2'>2</label>
<label><input type='radio' name='groupB' value='3'>3</label>
<br>

groupC:
<label><input type='radio' name='groupC' value='1'>1</label>
<label><input type='radio' name='groupC' value='2'>2</label>
<label><input type='radio' name='groupC' value='3'>3</label>
<br>

<script>
'use strict';
{
    window.addEventListener('DOMContentLoaded', function() {
        const
            radioElements = document.querySelectorAll('input[type=radio]'),
            state = {};

        for(let i = 0; i < radioElements.length; ++i) {
            radioElements[i].addEventListener('click', function() {
                if(state[this.name] === this.value) state[this.name] = this.checked = false;
                else state[this.name] = this.value;
            });
        }
    });
}
</script>
</body>
</html>
```
bulletml.jsの研究 その8

#概要

bulletml.jsの研究です。
技を調査。


#回転砲台


```
<bulletml>
	<action label="top">
		<repeat>
			<times>22</times>
			<action>
 				<fire>
  				<direction type="sequence">23</direction>
	  			<bullet>
						<action>
 							<changeDirection>
  							<direction type="sequence">0</direction>
  							<term>0</term>
 							</changeDirection>
						</action>
					</bullet>
 				</fire>
				<repeat>
					<times>100</times>
					<action>
 						<fire>
  						<direction type="sequence">23</direction>
	  					<bullet>
								<action>
 									<changeDirection>
  									<direction type="sequence">0</direction>
  									<term>0</term>
 									</changeDirection>
								</action>
							</bullet>
 						</fire>
 						<wait>5</wait>
					</action>
				</repeat> 
 				<wait>200</wait>
			</action>
		</repeat>
	</action>
</bulletml>
```

発射方向を変化させながら連続で撃つ攻撃です。
弾が螺旋状になることから、渦巻き弾とも呼ばれます。

#成果物

https://embed.plnkr.co/plunk/15HhxjaFYtUpFPFT

以上。
基本的なHTTPヘッダについて知る

## 主要なHTTPヘッダ
### Host
Httpヘッダ唯一の必須ヘッダです。
ブラウザからサーバに対して、サーバのホスト名とポート番号を指定します。

サーバが名前ベースの仮想ホストをサポートしている場合、同じサーバーアドレスでもHostヘッダで別々のホスト名を指定することで、仮想的に2つのサーバとして振舞うことができます。

仮想ホストとは、一台のサーバで複数のドメイン名によるサービスを提供すること。
ポート番号が指定されなかった場合は、要求されたサービスの既定のポートが設定されます（HTTPSは443、 HTTP は80）

### Content-type
実際にどんな形式のデータを送信したかを表すヘッダです。
レスポンスにおいては、ヘッダーはクライアントに返されたコンテンツの種類を伝えます。

リクエストでは、クライアントがサーバーに送られたデータの種類を伝えます。
レスポンスとリクエストの意味合いは一緒で、どちらも送ったデータの種類が何であるかを指定しておくものです。

### User-agent
クライアントのユーザーエージェントのバージョン等を識別できるようにするものです。

ブラウザが使用しているパソコンのブラウザの情報などを取得することができ、ユーザーエージェント情報を使い「スマートフォン」と「パソコン」の判定をして、表示するページの切り替えなどが可能です。

しかし、使用しているブラウザによっては、メニューから簡単にユーザエージェントを変更できてしまいます。
ユーザーエージェントは偽装も可能なため必ず正しい情報とは限りません。

### Accept
クライアント側が受信可能であるレスポンスデータのメディアタイプを指定します。

メディアタイプを省略した場合は，すべてのメディアタイプが受信可能であることを表す「*」が自動的に指定されます。

### Referer
現在表示しているページへのリンク先を持った、直前のウェブページのアドレスが含まれています。
 Referer ヘッダーにより、サーバーは人々がどこから訪問しに来たかを識別することができます。

次のような場合は、ブラウザーはRefererヘッダーを送信しません。

- 参照していたリソースがローカルの "file" または "data" の URI の場合
- 安全ではない HTTP リクエストが使用されており、それを参照しているページが安全なプロトコル (HTTPS) で受信された場合


### Refererの問題点・脆弱性
aタグにtarget="_blank"を設定をした場合、ちゃんとrel=noreferrerを設定する必要があります。しかし、なぜnoreferrerを設定する必要があるのでしょうか？

それは、URL 経由で他の場所に機密データを渡してしまう可能性があるということです。
noopenerを付けなければ、JavaScriptでwindow.openerというオブジェクトが操作できるようになり、 新しいタブで開いたページから元タブのページの操作が可能となります。

target="_blank"で開かれたページは、元のページを window.opener オブジェクトとして持つのでリンク先のページから window.openerを使うことで、元ページを操作することが出来てしまう。そのため、window.openerを使って「元ウィンドウを操作してフィッシングサイトに遷移されたり」悪用される可能性が考えられます。

また、refererを残したまま新しいタブで開いたリンク先で、いろんなscriptが動いてた場合、元ページのパフォーマンスにも影響があるとも言われています。

対処法としては、target="_blank"をつけたaタグに**rel="noopener noreferrer"**を設定することで解決できます。

### rel="noopener"
**「別タブの遷移先から、window.openerを参照できなくなる」**ものです。

### noreferrer
**「遷移元のリソースからリファラーを送らないようにブラウザに指示を出す」**効果があり、noopener と同様の効果も持ちます。

referer対策には、aタグにnoopener noreferrerの二つを設定されていることがありますが、noopener は古いブラウザではサポートされていません。 noreferrer の方がサポートしているブラウザは広いため、noopener を使えない場合として併用されています。
Chrome 88からtarget=_blankが付与されたリンクには、noopenerが自動的に付与されるようになるらしいです。

参照：https://forest.watch.impress.co.jp/docs/serial/yajiuma/1291549.html

### Accept-Encoding
クライアントがサポートしている圧縮方式をサーバーに教えるヘッダです。

 サーバーは送られてきた Accept-Encoding ヘッダの値を確認し、クライアントに合う圧縮アルゴリズムでコンテンツを圧縮して返却します。

```
例)
Accept-Encoding: gzip, deflate, br
```

### Authorization
クライアントからサーバーへ認証の種類やユーザ名・パスワード情報を知らせるものです。
認証の種類としては、例としてBasic認証などが使われます。

**Basic認証**は「ユーザー名：パスワード」の形式にコロンを挟んで連結してBase64形式へと変換したものとなります。

### Location
リダイレクト先のURLを示すHttpヘッダです。
Composer を 1.x から 2.x へアップデートする方法

# 前書き

Composer のアップデート記事は多々あれど「最低限なにすれば良いの？」という疑問に答えてくれる記事が見当たらなかったので書いた

# 検証環境

- Amazon Linux 2
- PHP
    - 7.2.4

## Composer 自身をアップデート

説明不要で、以下実行のこと

```bash
$ sudo composer self-update
Updating to version 2.0.9 (stable channel).
   Downloading (100%)         
Use composer self-update --rollback to return to version 1.9.2
```

念のため、バージョンを確認する

```bash
$ composer --version
Composer version 2.0.9 2021-01-27 16:09:27
```

無事、2.0.9 へ更新されていた

以上
GASでシートをコピーする

GASを使用してシートをコピーしたい時に以下のようなコードを書きました。

```
function copySheet(ss, targetSheetName, newSheetName) {
  var sheetTarget = ss.getSheetByName(targetSheetName);
  var sheetNew = sheetTarget.copyTo(ss);
  
  sheetNew.setName(newSheetName);
}
```

汎用性を持たせて上記のような形式にして、以下のように呼び出します。

```
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  copySheet(ss, "対象のシート名", "新しいシート名");
```

この場合、シートを丸々コピーするので、関数も全てコピーされるんですね。
関数をコピーじゃなくて値をコピーしたい場合があり、以下のようにしました。

```
function copySheetByValue(ss, targetSheetName, newSheetName, newSheetIndex, targetColumn) {
  var sheet = ss.getSheetByName(targetSheetName);
  
  // シート新規作成
  ss.insertSheet(newSheetName, newSheetIndex);
  var sheetNew = ss.getSheetByName(newSheetName);
  
  // コピーする内容を元シートから取得し、新シートに貼り付け
  var copyValues = sheet.getRange(1, 1, 1000, targetColumn).getValues();
  sheetNew.getRange(1, 1, copyValues.length, copyValues[0].length).setValues(copyValues);
}
```

呼び出し元は以下のような感じです。

```
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  copySheetByValue(ss, "対象のシート名", "新しいシート名", 1, 10);
```

コピーする時は、元シートから値を取得して新シートに貼り付けるということをやっています。

この場合、コピーする対象の範囲（行、列）を指定したり、値だけの貼り付けなので、書式もコピーしたい場合は別途対応だったり、もうちょっと良いやり方がある気がしています。
E/UncaughtException: java.lang.NoSuchMethodError: No virtual method load(Landroid/net/Uri;)Lcom/bumptech/glide/DrawableTypeRequest; in class の解決法

##エラー文
E/UncaughtException: java.lang.NoSuchMethodError: No virtual method load(Landroid/net/Uri;)Lcom/bumptech/glide/DrawableTypeRequest; in class Lcom/bumptech/glide/RequestManager; or its super classes (declaration of 'com.bumptech.glide.RequestManager' appears in /data/app/myapp/base.apk)

##解決法
glideの依存関係を削除すること。

例）
implementation 'com.github.bumptech.glide:glide:4.9.0'

##参考記事
https://github.com/bumptech/glide/issues/3539
AWS Certificate Manager (ACM)のDNS検証

ACMはAWSでSSL/TLS証明書発行および管理を代行してくれる便利なサービスです。

https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/acm-overview.html

以前はドメインの所有権確認をEメールで行っていましたが、2017年11月にDNSによるドメイン検証機能が追加されたので手動での検証作業から開放されました。

# 作業1 Route53でドメインを利用可能にする

DNSの検証にはRoute53の機能を利用します。
あらかじめ対象ドメインのCNAMEが編集できる状態にしておく必要があります。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128744/b6e56ba6-75bc-d13b-7334-af863eb66d0d.png)

# 作業2 Certificateのリクエスト

Certificate Managerの画面から証明書のリクエストを行います。
ACMではワイルドカード証明書も発行出来ます。
ネイキッドドメインと共通で利用する場合は画像のように、別の名前を追加でワイルドカード証明書を追加します。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128744/13d4acf1-1f2c-299f-89d2-c901dbe18a13.png)


# 作業3 DNSにCNAMEを追加

ドメインの所有権を確認するために、検証用のCNAMEレコードを提示されるので、その内容に合わせてCNAMEの追加を行います。
この時、Route53を利用しているとボタン一つで自動的にCNAMEを作成してくれるので便利です。
作業者のIAM権限にCNAMEの作成権限が無いとエラーになると思いますのでご注意ください。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128744/26e7bb51-3287-31c2-685b-fd5973ab0f50.png)

# 作業4 環境に証明書の設定を行う

証明書が必要なCloudFrontやALBに作成した証明書を設定すれば完了です。
一度この設定を行ってしまえば有効期限が近くなると自動的にACMが証明書の再発行を行ってくれるようになります。

# まとめ

証明書の有効期限を気にする必要がなくなりますので、ぜひ導入してみてください。
【Rails】星★を用いた評価機能の実装

#はじめに
Railsを用いたオリジナルアプリケーションを開発していた時の事。
投稿する際に、星を用いた評価機能があるとかっこいいと思いトライしてみたのですが
とても苦戦したので、振り返ることができるよう書き留めておきます。

#実現したい事
* 投稿ページで★を用いた評価をする。
![raty_post.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701834/00df409d-4da4-a253-0fa9-41f38a1dbe9f.gif)

* 一覧表示ページで、投稿時に設定された★の数を表示。
![rate_view.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701834/eff13f0d-8439-0caa-d5b3-9e6bf848ffa5.png)

#postsテーブルの作成
postsテーブルにrateカラムを作成します。
今回、`1.5` や `3.5` のように、`0.5`刻みで評価値を設定したいので、カラムの型は`float型`とします。

#jQueryの導入
まずはGemfileに以下の記述を加え、忘れずに`bundle install`します。

```Gemfile:Gemfile
gem 'jquery-rails'
```
次に`application.js`に次のコードを追記します。

```js:application.js
window.jQuery = window.$ = require('jquery')
```
この時`package.json`の編集も必要らしいのですが、ターミナルで次のコマンドを実行すればオッケーらしいです。

```
yarn add jquery
```
(jQueryの導入に関しては`yarn add jquery`コマンドが何をしてくれているのかあまり分かっていないので、分かる人からしたら効率の悪い導入方法だと思われてしまうかもしれません。)

#jsコードと画像の読み込み
###jsコード
下記のGitHubからコードをコピーして、`jquery_raty.js`などと適当に名前をつけて`application.js`の近くに配置します。

https://github.com/wbotelhos/raty/blob/master/lib/jquery.raty.js

次に`application.js`から`require`します。

```js:application.js
window.jQuery = window.$ = require('jquery')

require("../jquery_raty") //追加
```
`require`する際の`jquery_raty.js`のパスはファイルの配置位置によって人それぞれなので注意です。

###画像
下記のGitHubから画像を持ってきます。
`star-half.png`、`star-off.png`、`star-on.png`の3つの画像を`app/assets/images`配下に保存します。

https://github.com/wbotelhos/raty/tree/master/lib/images

#星を用いた評価の入力と保存

```rb:new.html.erb
 <div class="" id="star">
   <%= f.label :rate,'評価 :', class:"" %>
   <%= f.hidden_field :rate, id: :review_star %>
 </div>

 <script>
 $('#star').raty({
   size     : 36,
   starOff:  '<%= asset_path('star-off.png') %>',
   starOn : '<%= asset_path('star-on.png') %>',
   starHalf: '<%= asset_path('star-half.png') %>',
   scoreName: 'post[rate]',
   half: true,
 });
 </script>

```
大きさの調整は`class=""`で任意に設定してください。
また、下記1行目でPostモデルのrateカラムに値を保存。2行目の記述で`0.5`刻みの星による評価を許容しています。

```
scoreName: 'post[rate]'
half: true,
```

#評価の表示

```rb:index.html.erb
 <div class="">
   <div id="star-rate-<%= post.id %>"></div>
   <script>
   $('#star-rate-<%= post.id %>').raty({
     size: 36,
     starOff:  '<%= asset_path('star-off.png') %>',
     starOn : '<%= asset_path('star-on.png') %>',
     starHalf: '<%= asset_path('star-half.png') %>',
     half: true,
     readOnly: true,
     score: <%= post.rate %>,
   });
   </script>
 </div>
 <div class="">
   <%= post.rate %>
 </div>
```
省略していますが、`post`に情報を入れて`each`で回しています。
`class`はお好みで設定してみてください。

#まとめ
星★を用いた評価機能を実装するだけで、見た目がガラッと変わり感動しました。
苦戦はしましたが、他にも実装したい機能あればどんどん挑戦していきたいです。

#参考
* [【Rails】レビュー用の星★の評価を実装する（入力、保存、表示） - Qiita](https://qiita.com/yuki_0920/items/a966d9fa2bdb621f805d)
* [jquery.raty rails導入 - Qiita](https://qiita.com/baek_seo/items/dcc38e8b23def28b8f1a)
* [【Rails入門】5分でできるjQuery導入方法!初心者向けにまとめました](https://www.sejuku.net/blog/57790)
* [railsでjqueryを導入したい。 - teratail](https://teratail.com/questions/259128)
Intuneでlog analytics agentを配布して、従業員のPC起動時間をモニタリングする。

#実現したい事
Intuneで全社員のWindowsPCにlog analytics agentを配布する！(with Azure)
Azure モニターでいつでもWindowsログを見れるようにする。

## zennに移動しました。
https://zenn.dev/jun6428/articles/c467c0fa3585c2
[SwiftUI][iOS14]PageTabViewStyleでPageControlの色を変える

iOS14から`TabView`に`PageTabViewStyle`が追加されました。iOS13では、UIPageViewControllerに相当するクラスがなかったのですが、`PageTabViewStyle`で実現できるようになったので、UIViewRepresentableを使わなくなるので便利です。
しかし、１つ難点がarimasu.`UIPageControl`が下の方に表示されるのですが、デフォルトで白でSwiftUIでは変更ができません。

色々調べた結果、UIKitのUIAppearanceを使うしか今のところ方法がないことがわかりました。

## 通常の使い方
UIPageControlの表示が白なので、背景を黒くしています。

```swift
struct ContentView: View {
    var body: some View {
        
        TabView {
            Text("タイトル１").foregroundColor(.white)
            Text("タイトル２").foregroundColor(.white)
        }.tabViewStyle(PageTabViewStyle.init(indexDisplayMode: .always))
        .background(Color.black)
        .edgesIgnoringSafeArea(.all)

    }
}
```
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297014/7993ff07-4a6a-656d-ea08-2ebc79f5d34e.png"/>

## UIPageControlの色を変える

SwiftUIのみではUIPageControlのパーツの色を変えることはできませんが、UIAppearanceを使えば変更が可能です。

```swift
import SwiftUI
import UIKit

struct ContentView: View {
    
    init() {
        UIPageControl.appearance().currentPageIndicatorTintColor = .red
        UIPageControl.appearance().pageIndicatorTintColor = UIColor.white.withAlphaComponent(0.8)
    }
    
    var body: some View {
        
        TabView {
            Text("タイトル１").foregroundColor(.white)
            Text("タイトル２").foregroundColor(.white)
        }.tabViewStyle(PageTabViewStyle.init(indexDisplayMode: .always))
        .background(Color.black)
        .edgesIgnoringSafeArea(.all)

    }
}
```

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297014/0ad32f7f-bfde-c577-3dab-863f285c0a43.png"/>

## 参考

https://developer.apple.com/forums/thread/83563
Bashで指定した範囲での乱数を出力する

# やりたいこと
35.5 ~ 36.9のあいだで乱数を出したい
0からxまでの乱数はかんたんだが、0以外からの乱数は難しかった。

# コード

```bash
#!/usr/bin/env bash
list=($(seq 355 369))
declare -i out=0
while (( out == 0)); do
    out=$(printf "%s\n" "${list[@]}" | head -n $(( RANDOM % ${#list[@]})) | tail -n 1)
done
echo "scale=1; ${out} / 10" | bc
```
少数の扱いは面倒なので整数を最後に10で割った。
seqで出力してから、0から行数分までの乱数でランダムに1行取り出す
ただし乱数が0になると何も出力されないので`while`で0以外になるようにループさせた。

# 最後に
絶対もっとかんたんで賢い方法がある。配列とか変数とか使っててめちゃくちゃ面倒。
とりあえずcudaが使いたい人のためのQiita

# Dockerを使いましょう
Docker知らないからってこのページを閉じようとしたあなた。多分想像以上に環境構築簡単なのでご安心を。Dockerさえ入ってしまえばLinuxのOSやversionが関係ないのがDockerの強みです。
# 背景
私事ながら、Geforce RTX3090を手に入れたのですが、今までのcudaの導入方法だと一向に認識されず、1週間溶かしまして絶望していたのですが、Dockerを使えば一瞬でしたので同じように悩んでる人に向けてそれを共有したいと思いました。
# 環境
- Ubuntu 18.04（GPUが接続されているLinuxならDockerさえ入ればなんでもいい）

# やり方
## 1. Dockerのインストール
たくさんの記事があるので割愛。
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04-ja
などを参照。
## 2. 使いたいDocker imageを探す
[Docker hub](https://hub.docker.com)で使いたいDockerイメージを探します。色々ありますがとりあえずcudaが使いたい人は[nvidia/cuda](https://hub.docker.com/r/nvidia/cuda)の最新のものにしましょう。`base`, `runtime`, `devel`とありますが、特にこだわりがなければ`devel`を選択するのが良いでしょう。（`devel`にしかないコマンドがある）

>
base： 事前ビルドされたCUDAアプリケーションを展開するための最小構成のイメージ。CUDA Toolkit 9.0以降のみ。
runtime： CUDA toolkitから全ての共有ライブラリを追加したCUDA実行用のイメージ。
devel： 共有ライブラリだけでなくコンパイラーチェーン、デバッグ用ツール、スタティックライブラリなどが追加されたCUDA開発用のイメージ。
https://www.atmarkit.co.jp/ait/articles/1804/18/news141_3.html

以下で用いるDockerイメージは`nvidia/cuda:11.2.0-runtime-ubuntu20.04`とします。
（ちなみにコロンの前の`nvidia/cuda`を`REPOSITORY`, コロンの後の`11.2.0-runtime-ubuntu20.04`を`TAG`といいます）
## 3. Docker pull
個人的には`Git`でいう`git clone`という理解をしています。使いたいDockerイメージをローカルに作成します。今回は`nvidia/cuda:11.2.0-runtime-ubuntu20.04`を用いるので、

```shell

docker pull nvidia/cuda::11.2.0-runtime-ubuntu20.04
```

となります。`docker pull`は時間がかかるので気長に待ちましょう。
## 4. コンテナを生成、起動
dockerイメージのコピーであるコンテナを生成し、その中に入っちゃいます。

```shell
docker run -it nvidia/cuda::11.2.0-runtime-ubuntu20.04
```
すると、謎の場所に連れて行かれると思います

```sh
[root@4ae03cb199f4 /]#
```

これで起動成功です。ここはcudaの入ったubuntu20.04の世界になっています。

あとはこの中でいつも通り環境を構築していきましょう。（僕は`anaconda`を入れました）もし何か失敗してしまってもコンテナを消してまた1から作ればOKです。ホストOSが汚染されることはありません。

## Dockerの使い方について
ちなみに上の方法をそのままやったところでろホストOSのディレクトリは覗けませんし、ipアドレスが繋がってないのでサーバーを立てることもできません。ここからどうカスタマイズしていくかは使う人にかかってきます。ぜひ色々と調べてみてください。（私も絶賛Docker勉強中であります）
例えば`anaconda`を使うなら、`-v`で接続するディレクトリを決めて`-p`でポート番号を指定したりするとコンテナ内の環境でホストのファイルの操作ができるようになります。

# 参考
https://www.amazon.co.jp/Docker実践ガイド-第2版-impress-top-gear/dp/4295005525
inkscapeを使ってミニマムなSVGを作る

illustratorを使わずに、inkscapeで記述の少ないSVGを作る手順です。

1.pngファイルなどをInkscapeで開く

2.表示された画像を選択状態にする
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150548/cc2803b6-9dfa-17e9-76a5-9b52431ac608.png)

3.パス(P) => ビットマップのトレース
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150548/f668333a-a08d-050d-119a-f5bb8f1f241a.png)

4.オブジェクト(O) => Objects
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150548/765ad439-2c87-4bcf-f85e-5575b1c896e8.png)

5.pathを残して、imageを削除
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150548/a83269a0-5d4f-e535-73d1-aef7ae5fcc9b.png)

6.オブジェクト(O) => フィル/ストローク
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150548/51b1bab4-61de-28c6-a6a0-9c371964deb2.png)

7.ストロークの塗り で単一色などを選ぶ
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150548/663fbc90-2ab6-7b8e-2b06-61f8e551d418.png)

8.ファイル(F) => 名前を付けて保存

9.export方式は 最適化svg を選択

10.このようなSVGファイルができます
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150548/65b9abcf-10fb-8559-673f-4f15105dc5a7.png)
RX6800 複数枚差しは Above 4G decoding enabled にしないと認識しない(2021/01/28 時点)

RX6800 はベンダーが異なるもので確認しました.

Windows, Linux 最新ドライバ(2021/01/28 時点) + X570 マザー(異なる 3 種類)で確認しました.

RX6800 はメモリ量多いからか, そのままでは複数枚差しを認識してくれません.
正確には, lspci や GPU-Z などでは複数 GPU あるのは認識されているが, OpenCL が複数枚認識しない. 

BIOS で Above 4G decoding しないと認識しないようです
(Windows のみで確認)

とりあえずは複数 RX6800 で OpenCL 機械学習, Vulkan レイトレ(ただこちらは Vulkan Linux ドライバがまだ), マイニングしたい場合は Above 4G decoding の設定のあるマザーボード(or BIOS update)使いましょう. 設定が無い BIOS では動かないでしょう.

## TODO

* [ ] Linux + Above 4G decoding on で認識されるかどうかためす
git push heroku masterでruby-2.6.5 on heroku-20とエラーが出た件

# はじめに
今回はHerokuでのデプロイの際に以下のようなエラーが出たので解決策を記録しておこうと思います。

```ruby:ターミナル
remote:  !
remote:  !     The Ruby version you are trying to install does not exist on this stack.
remote:  !     
remote:  !     You are trying to install ruby-2.6.5 on heroku-20.
remote:  !     
remote:  !     Ruby ruby-2.6.5 is present on the following stacks:
remote:  !     
remote:  !     - cedar-14
remote:  !     - heroku-16
remote:  !     - heroku-18
remote:  !     
remote:  !     Heroku recommends you use the latest supported Ruby version listed here:
remote:  !     https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
remote:  !     
remote:  !     For more information on syntax for declaring a Ruby version see:
remote:  !     https://devcenter.heroku.com/articles/ruby-versions
remote:  !
```

# 開発環境

- Ruby 2.6.5
- Bundler 2.1.4
- Rails 6.0.0
- MySQL 5.6.50

# 解決方法

結論から言うと`Herokuのstack`が`ruby 2.6.5`に対応していないのが原因です。
今回の場合だと、`stack-20`が対応していないので、**stackのバージョンを下げることで解決できます**。

エラー分の真ん中あたりにも
`heroku-16`
`heroku-18`などと提案してくれているので、`stack-18`にバージョンを下げます。

ターミナルで以下のコマンドを実行します。

```ruby:ターミナル
% heroku stack:set heroku-18 -a アプリ名
# 以下のように出力されれば成功
Setting stack to heroku-18... done
```

次に`heroku apps:info`コマンドでバージョンを確認してみましょう。

```ruby:ターミナル
% hroku apps:info
=== my_app
Addons:         cleardb:ignite
Auto Cert Mgmt: false
Dynos:          
Git URL:        https://git.heroku.com/my_app.git
Owner:          メールアドレス
Region:         us
Repo Size:      0 B
Slug Size:      0 B
Stack:          heroku-18
Web URL:        https://my_app.herokuapp.com/
```

stackが`heroku-18`になっていることを確認しましょう。

ここまで来たら、Commit履歴を残しておくといいでしょう。

```ruby:ターミナル
% git commit --allow-empty -m "Downgrading to heroku-18"
```

ターミナルで以上のコマンドを実行するとGitにCommit履歴が残っているので、pushしておきましょう。

ここまで来たらHerokuにpushしてデプロイしましょう。
`git push heroku master`をターミナルで実行し、デプロイをしましょう。
SwiftUIでドロップダウンリストを作成する

## 概要
SwiftUIで、ドロップダウンリスト（Windowsでいうコンボボックスみたいな）UIをどう実現できるか調べた。
（Pickerでも複数リストから単一の値を選択できるが、Pickerのドラムロールっぽい見た目はあまり好きではない）

## 環境
iOS14

## 調査結果
View部分をViewBuilderで差し込んだり、フォントサイズとかもろもろいろいろ改善の余地はありそうだけど、
テキストだけのドロップダウンリストであればこんなようなものをつくればできそう。  

```swift
struct DropdownList<Content: CustomStringConvertible & Hashable>: View {
    private let list: [Content]
    @Binding var selected: Content
    var body: some View {
        Menu {
            ForEach(list, id: \.self) { content in
                Button {
                    selected = content
                } label: {
                    Text(content.description)
                }
            }
        } label: {
            HStack {
                Text(selected.description).lineLimit(1)
                Text("▼")
            }
        }
    }
}
```

## 備考
iOS14以降でしか使えない
[まとめ]HTML/CSSについて

会社の試験に向けてHTML/CSSの復習をしています。
その中で「あ！忘れてるな」と思った部分があったのでまとめてみます。

#CSSの構成
CSSはセレクタ・プロパティ・値で構成されています。
次のコードを例にすると

```css:css
body {
  background-color: white;
}
```

>セレクタ　　⇨　body　(CSSによる装飾を、どの部分のHTMLに適用するか)
>プロパティ　⇨　background-color　(何を変えるのか)
>値　　　　　⇨　white　(設定する内容)

となります。


#class属性とclassセレクタ、id属性とidセレクタ
class属性とはHTML要素に対して個別に名前を指定することができる属性
id属性とは特定のHTML要素のみに対して、名前を指定することができる属性
※id属性には**「1つのページ内で、同じid名を複数のHTML要素に付与しない」**というルールがあります。

次のhtmlコードを例に説明します。

```html:html
<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
    <title>旅行予約サイトA</title>
    <link rel="stylesheet" href="tripstyle.css">
  </head>
  <body>
    <h1>
      国内旅行
    </h1>
    <p>
      沖縄
    </p>
    <p>
      石垣
    </p>
    <p>
      宮古島<b>この部分は太字になります。</b>
    </p>
     <a href="https://www.google.com/">クリックすると、Googleへ移動します。</a>
  </body>
</html>
```

\<p>石垣\</p> のみを装飾したい場合
複数のp要素がある中で一部のp要素のみを装飾したい場合はclass属性を使います。
>記述例：\<p class="ishigaki">

\<p>宮古島\</p>のみを装飾したい場合
特定のHTML要素のみに対して、名前を指定したい場合はid属性を使います。
>記述例：\<p id="miyakojima">

CSSへは次の様に記述することでそれぞれの装飾が反映できます。

```css:css
p {
  font-size: 24px;
  color: red;
}
.ishigaki {
  color: orange;
  font-size: 12px;
}
#miyakojima {
  color: blue;
}
```

#span要素
テキストの一部だけを装飾したい場合に使います。
※部分的にテキストのフォント調整、文字色・背景色を変更する場合など

装飾したいテキストの前後を\<span>...\</span>で囲み、span要素にクラスを設定
>\<span class="red">装飾したいテキスト\</span>

CSSファイルで、クラスにプロパティを設定する
>.red {
  color: blue;
}

これで、装飾したいテキストにのみ適用されます。

#ul要素とli要素
ul要素
順序のないリストを示すブロックレベル要素、li要素の親要素となります。
li要素
リストの項目を示すブロックレベル要素です。ul要素の子要素です。
次の様に記述します。

```html:html
<ul class="lists">
  <li class="list">北海道</li>
  <li class="list">東京</li>
  <li class="list">大阪</li>
  <li class="list">福岡</li>
</ul>
```

```css:css
.list{
  list-style: none;
}
```
>値を指定しない場合箇条書きの頭に・がつきます。
値としてsquareを指定すると箇条書きの黒点を■で表現できます。
値としてnoneを指定していると、箇条書きの黒点を消すことができます。


リストのうち、一箇所だけ装飾をしたい場合は
追加でCSSを追加したい部分だけに、新たにclassを追加する
＝半角スペースで区切ることによって、1つの要素が複数のクラスを持つことができます。

```html:html
<ul class="lists">
  <li class="list">北海道</li>
  <li class="list">東京</li>
  <li class="list">大阪</li>
  <li class="list jimoto">福岡</li>
</ul>
```

```css:css
.lists{
  list-style: none;
}

.jimoto{
  background-color: yellow;
}
```

####基礎中の基礎！だと承知していますが、ほんと〜〜に忘れっぽいのでまとめました。

記事の頭に[memo]がついているものは実装手順がわからなくなりそうなものだったり、
理解を深めるためのメモ記事になります。今回はいくつかのまとめなので[まとめ]にしました。
heroku + さくらのドメインの設定

# heroku + さくらのドメインの設定
## TL;DR
クレジットカード情報を登録すれば無料で独自ドメインを設定可能
Herokuのアプリにドメインを追加して返ってきたDNS Targetをさくらのドメインのゾーン設定の値に入力(末尾に`.`をつける)。種別はCNAMEで新規登録
## 背景
軽く検索してヒットはしたが、情報が古いかなと感じたので
## 前提
ドメインは取得済み
Herokuで検証済みアカウントとなっている（クレカ登録済み）
## 前準備
サブドメインを決定する。
## Herokuでの設定
対象のアプリのHerokuの管理ページを開き、Settingsタブを開きます。
DomainsのAdd domainボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751601/b6bd11b5-4ab6-8464-ecee-bb6ac289959a.png)

Domain nameに登録したいドメインを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751601/2b69954a-35f1-fc1d-2053-5b9a0e550b68.png)

NextボタンをクリックするとDNS targetが表示されるので控える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751601/0dd3a3e4-b048-9ce5-8d30-8675549dc597.png)
これでHeroku側での操作は完了

## さくらのドメインでの設定
会員メニュー>契約中のドメイン一覧>ドメインメニュー
割り当てたいドメインのゾーン編集>変更
エントリ名：[サブドメイン].example.com
種別：CNAME
値：さっき控えたDNS targetを貼り付け、末尾に`.`を追加
DNSチェック：する
TTLの指定：チェックなし
で新規登録

これでさくらのドメイン側も完了

## ドメインの浸透
最大48時間だったり72時間だったり書いてあるが自分の場合は1分経たずにつながった

## ドツボポイント
`.`
ちなみにこれはHerokuのドキュメントにもさくらの設定画面にも書いてある。
WSL環境にblobfuseをインストールしてAzure Storageにアクセスする

## はじめに
WSL/Linux環境からAzure Storage (Azure blob storageやAzure data lake storage gen2)にアクセスしたい場合が多いのではないのでしょうか。
そういった場合にAzure StorageをLinux環境へマウントできるBlobfuseを使うとはかどります！

## Microsoftのリポジトリを追加する
Ubuntu 20.04 環境の場合：

```bash
curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
sudo apt-add-repository https://packages.microsoft.com/ubuntu/20.04/prod
sudo apt-get update
```

## blobfuseをインストール

```bash
sudo apt-get install blobfuse
```

## マウントの準備
バッファとして使用するディレクトリを作成する。

```bash
sudo mkdir /mnt/resource/blobfusetmp -p
sudo chown <username> /mnt/resource/blobfusetmp
```

ストレージアカウントの資格情報ファイルを作成していきます。

```bash
vim ~/fuse_connection.cfg
```

任意のテキストエディタでファイルを開いたら、次の内容を書き込みます。

```
accountName <myaccount>
accountKey <storageaccesskey>
containerName <mycontainer>
```

他のユーザーが見えないようアクセス権を制限します。

```bash
chmod 600 ~/fuse_connection.cfg
```

マウント用の空ディレクトリを作成します。

```bash
mkdir ~/azurestorage
```

マウントします

```bash
sudo blobfuse ~/azurestorage--tmp-path=/mnt/resource/blobfusetmp  --config-file=/path/to/fuse_connection.cfg -o attr_timeout=240 -o entry_timeout=240 -o negative_timeout=120 -o allow_other
```

## アンマウント

```bash
sudo fusermount -u azurestorage
```
でアンマウントできます。

## 

## 参考文献
https://docs.microsoft.com/ja-jp/windows-server/administration/Linux-Package-Repository-for-Microsoft-Software
https://qiita.com/mihomiporin1110/items/177e4f3e2f42ef86becf
UIScrollViewが慣性スクロール中かどうか知る

## 概要
UIScrollViewがスクロール中かどうかを知りたかったので、方法を調べた。

## 環境
- iPadOS14.2
- iOS14
- swift

## 結果
ペンシルのことを考慮しない場合は

```swift
UIScrollView.isDecelerating
```

というプロパティが生えているので、これを使うことができる。 
※詳しく調査していないが、以前はこれだけだと問題があったようだが、現時点（iOS14）では（ほぼ）これでうまくいく

ただ、慣性スクロールを指で止めた場合は問題ないが、ペンシルで止めた場合、isDeceleratingがtrueになりっぱなしで困った。

調査の結果、以下のようなワークアラウンドで回避できた。

```swift

extension UIScrollView  {
    // こんな処理を用意してあげて
    func stopDecelerating() {
        let contentOffset = self.contentOffset
        self.setContentOffset(contentOffset, animated: false)
    }
}

// 対象のUIScrollViewのtouchesShouldBeginなどをオーバーライドして、
// ペンシルの場合は、明示的にスクロールを止める
class HogeView: UIScrollView {

    override public func touchesShouldBegin(
        _ touches: Set<UITouch>, with event: UIEvent?, in view: UIView
    ) -> Bool {

        if isDecelerating && touches.contains(where: { $0.type == .pencil }) {
            stopDecelerating()
        }
    }
}
```

## 参考
- https://qastack.jp/programming/993280/how-to-detect-when-a-uiscrollview-has-finished-scrolling
- https://stackoverflow.com/questions/3410777/how-can-i-programmatically-force-stop-scrolling-in-a-uiscrollview