OmniAICreator/Qiita-1.07M huggingface dataset:
PHPの基本操作③ 「入力欄、ラジオボタン、チェックボックス」

##参考書籍
よくわかるPHPの教科書 PHP7対応版

##他記事リンク
- [PHPの基本操作①<br>「簡単な出力と構文、配列、連想配列、少数、フォーマット」](https://qiita.com/kunrenyouAcount/items/7a3bb6e5769ba94a7dc5)

- [PHPの基本操作②<br>「ファイルの読み込み、ファイルの書き込み、XMLの読み込み、JSONの読み込み」](https://qiita.com/kunrenyouAcount/items/bec393cae5901e32ec70)

- [PHPの基本操作③<br>「入力欄、ラジオボタン、チェックボックス」](https://qiita.com/kunrenyouAcount/items/1c66ccee97c33f320fb2)

- [PHPの基本操作④<br>「数字かどうかの判定、正規表現、別ページにジャンプ」](https://qiita.com/kunrenyouAcount/items/5b292d8481a76386fd1e)

- [PHPの基本操作⑤<br>「クッキーとセッションの保存と取得」](https://qiita.com/kunrenyouAcount/items/7324fad1d3d1845de075)

- [PHPの基本操作⑥<br>「電子メールの送信」](https://qiita.com/kunrenyouAcount/items/2172f03af0d8d8a32cc6)

- [PHPの基本操作⑦<br>「ファイルアップロードの受信をする」](https://qiita.com/kunrenyouAcount/items/dece31f962472fb23610)


##フォームに入力した内容を取得する

以下は「submit.php」宛に送信するフォームです。

```html:フォームのHTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="submit.php" method="get">
      <label for="my_name">お名前:</label>
      <input type="text" name="my_name" maxlength="255">
      <input type="submit" value="送信する">
    </form>
  </body>
</html>
```

送信されてきたデータを受け取るときには、name属性を指定して取得します。例えば名前の入力欄の値を取得するときには、以下のように記述します。

```php
$_GET['my_name'];
```

※上記のformのmethodがGETのため。POSTの時には$_POSTを使う


しかし入力欄に「<」と「>」で囲まれた値がある場合、それをHTMLとして受け取ってしまい、画面に正しく表示されません。
そのため、うけとった値のHTMLタグの効果を打ち消すためにhtmlspecialchars関数を使います。

```php
htmlspecialchars($_GET['my_name'], ENT_QUOTES);
```

実際に取得して出力するには以下のように記述します。

```php:submit.php
お名前: <?php print(htmlspecialchars($_REQUEST['my_name'], ENT_QUOTES)); ?>
```


##ラジオボタンの値を取得する
以下は「submit.php」宛に送信するフォームです。

```html:フォームのHTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="submit.php" method="post">
      <p>性別：
        <input type="radio" name="gender" value="male">男性／
        <input type="radio" name="gender" value="female">女性
      </p>
      <input type="submit" value="送信する">
    </form>
  </body>
</html>
```

ラジオボタンの場合も同様に、name属性を指定して取得をします。

```php:submit.php
性別：
<?php
  print(htmlspecialchars($_POST['gender'], ENT_QUOTES));
?>
```

※しかし、取得されるのはタグに囲まれている値ではなく、valueの値なので注意が必要です。


##チェックボックスの値を取得する
以下は「submit.php」宛に送信するフォームです。
複数選択可能なチェックボックスなどをformで作成する場合には、必ず「[]」という記号をname属性に付与してください。そうすることで、PHP側で取得した時に取得した値を配列として扱うことができ、複数の値を扱えます。

```html:フォームのHTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <form action="submit.php" method="post">
      <p>ご予約希望日（複数選択可)</p>
      <p>
        <input type="checkbox" name="reserve[]" value="1/1">1月1日<br>
        <input type="checkbox" name="reserve[]" value="1/2">1月2日<br>
        <input type="checkbox" name="reserve[]" value="1/3">1月3日<br>
      </p>
      <input type="submit" value="送信する">
    </form>
  </body>
</html>
```

name属性を取得する時には、「[]」は省略します。
取得した値は自動的に配列になります。

```php:submit.php
ご予約日：
<?php
  foreach($_POST['reserve'] as $reserve) {
    print(htmlspecialchars($reserve, ENT_QUOTES) . ' ');
  }
?>
```
シバン( shebang )は .bashrc , .zshrc 等に必要なのか否か?

# シバン( shebang )は .bashrc , .zshrc 等に必要なのか否か?

最近シェルスクリプトを書いているときに、(シバン)shebangの必要性を実感し、
.bashrcや.zshrcなどのdotfilesを書いているときに、ふと、.bashrcや.zshrcには一般的にシバン(shebang)は必要ないのか必要なのか? 気になったのでその考察メモ。

※個人的な考察なので、間違い等がありましたら議論や、ご指摘等いただけると幸いです。

# シバン(shebang)とは?

shebangの#!の意味は難しいです。(私も現在勉強中です)
これはコメントではないのです。

先に結論だけを言えば、Magic numbersのことです。

asciiコードを16進数に変換しても同じようにコマンドは実行できるということを考えるとイメージができるかもしれません。

```bash
#!/bin/bash
ls
```

```bash
eval $'\x23\x21\x2F\x62\x69\x6E\x2F\x62\x61\x73\x68'
eval $'\x6c\x73'
```
そう、Magic numbers とはこの 0x23 0x21 のことです。これはそれぞれ # ! を表しています。

以下を実行してみると理解できるはずです。

```bash
echo -e '\x23'
echo -e '\x21'
```

※もう少し、このMagic numberやシバンの本質的な役割等を理解できたら追記したいと思います。

ここで、また別の疑問も浮かんでいます。

そもそもなぜシバン(shebang)というのでしょう、全くイメージが湧きません。

これは、shebangというのがスラングのようなもので、実際の意味はSituationだと思われます。[^2]

#### シバン(Shebang)はシチュエーション(Situation)のスラングなんだと思うと、何だか急にイメージできませんか。

また、なぜシバン(shebang)を書かなければいけないのかというと、

>You can have scripts without the shebang. In this case the shell that you launch the script from will be used to interpret the script. This can, obviously, lead to complications, on other systems or with other users.
A shebang looks like this: [^1]

```bash
#!/bin/bash
```

とあります。
もちろんシバン(shebang)がなくても、スクリプトを作成、実行はできるということですね。

ではなぜシバン(shebang)が必要なのでしょうか。

この場合、スクリプトを起動するシェルがスクリプトの解釈に使用されるということです。

ただ、お分かりのように、これは明らかに、他のシステムや他のユーザとの間で複雑になる可能性があります。

実際にやってみると以下のように、zshのみにしかサポートされてない構文に対してエラーが出ます。

まず、.zshrcをコピーして、shebangをそれぞれ`/bin/zsh`と`/bin/sh`にして検証してみます。

```bash
$ which zsh
$ which sh
$ cp .zshrc zshrc
$ chmod 755 zshrc
$ ./zshrc
```

コピーしたzshrcにshebangを加えてみる。

```zsh:shebang->zsh
#!/bin/zsh
echo hoge
# 不要なので省略
fpath=(~/.zsh/completion $fpath)
autoload -Uz compinit && compinit -i
zstyle ':completion:*:default' list-colors ${(s.:.)LSCOLORS}
# 以下不要なので省略
```


```zsh:shebang->sh
#!/bin/sh
echo hoge
# 不要なので省略
fpath=(~/.zsh/completion $fpath)
autoload -Uz compinit && compinit -i
zstyle ':completion:*:default' list-colors ${(s.:.)LSCOLORS}
# 以下不要なので省略
```

![スクリーンショット 2021-04-23 22.49.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1009976/8b48b22b-5b96-e665-45c9-3f7c42a460a0.png)

ここで、そうなんです、実行権限を与えて、そのまま実行されるとシバンが読まれるようです。

次に、実際に`.zshrc`に直接`#!/bin/sh`を記述しても、特に変わりなくロードされて、問題なく使用できます。
![スクリーンショット 2021-04-23 23.02.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1009976/b1c9cd8a-d841-87c3-526e-128370236382.png)

このように記述して、ターミナルを再起動しても、シバンが読まれることはありませんでした。

ここまでの、検証の結果、今回私の結論としては.bashrcや.zshrcにシバン(shebang)を記述することは、無駄なリソースなので、必要ないと判断しました。

# 最後に

同じような疑問を記事等にしているものを見つけられなかったので今回記事にしてみました。
私の周りにも、.zshrcや.bashrcなどのdotfilesにもシバン(shebang)は書くべきだという人もいれば、書かなくてもいいという人もいて様々だったので、今回考察をしてみました。

もし、「いや私はシバンを書くべきだ」とか、「確かにシバンは書かなくてもいい」など、意見がありましたらコメント等いただけると幸いです。
私自身、未熟なので、間違い等発見されましたら同様にコメントにて教えていただけると幸いです!

[^1]: On the Shebang https://scriptingosx.com/2017/10/on-the-shebang/  
[^2]: Shebang meaning https://www.yourdictionary.com/shebang/
NameErorrのエラー出現

今日の備忘録、というか完全に初歩的なミス
※前提として、この時deviseで作成したAdminのためのマイページを作成するため、専用のAdminsコントローラーとviewを作ってました。ルーティングはAdminとUserの複数モデルを管理していたため、namespaceで分けて記載。

NameErorrのエラーが発生し、クラスの名前や指定するルーティングをミスったのかと思い何度も確認。

全く間違いぽいものは見つからず、その時は確認すらしなかったroutes.rbにしっかりミスが。

routes.rbを確認すると、

``` /config/routes.rb
Rails.application.routes.draw do

  devise_for :admins, controllers: {
    sessions:      'admins/sessions',
    passwords:     'admins/passwords',
    registrations: 'admins/registrations'
  }
  devise_for :users, controllers: {
    sessions:      'users/sessions',
    passwords:     'users/passwords',
    registrations: 'users/registrations'
  }

  namespace :admins do
    root 'post_images#index'
    resources :post_images, only: [:new, :create, :index, :show, :destroy]
  end

  scope module: 'users' do
    root 'home#top'
    resources :users, only: [:show, :edit, :update]
    resources :post_images, only: [:new, :create, :index, :show, :destroy] do
      resources :post_comments, only: [:create, :destroy]
    end
  end
end
```

namespace :adminsの中に書いていると勝手に思い込んでいたresources :adminsが書いてない、てか書いた痕跡もない。

早急に修正

``` /config/routes.rb
Rails.application.routes.draw do

  devise_for :admins, controllers: {
    sessions:      'admins/sessions',
    passwords:     'admins/passwords',
    registrations: 'admins/registrations'
  }
  devise_for :users, controllers: {
    sessions:      'users/sessions',
    passwords:     'users/passwords',
    registrations: 'users/registrations'
  }

  namespace :admins do
    root 'post_images#index'
    resources :post_images, only: [:new, :create, :index, :show, :destroy]
    resources :admins, only: [:show, :edit, :update]
  end

  scope module: 'users' do
    root 'home#top'
    resources :users, only: [:show, :edit, :update]
    resources :post_images, only: [:new, :create, :index, :show, :destroy] do
      resources :post_comments, only: [:create, :destroy]
    end
  end
end
```

誰もこんな初歩的なミスはしないと思うのですがもし誰かの参考にでもなれば嬉しいです。
爆速でWordpressのDocker環境を作成する


最近、wordpressの構築が増えてきたので覚書目的でWordpressのDocker環境用テンプレートを作成しました。
インフラに興味がなく、とりあえず爆速で動く環境が欲しい人用なので、設定方法など興味があれば他の記事を参考にしてください。

よかったら使ってみてください。

https://github.com/ateliee/wordpress-docker

環境
-----
* Wordpress(最新安定版)
* MySQL
* MailHog(テストメール用)

使い方
------

「Use this template」もしくはリポジトリをcloneして、docker環境を立ち上げるだけです。

```shell
git clone git@github.com:ateliee/wordpress-docker.git
cd wordpress-docker
make up
```

Wordpressのバージョンを変更したい場合は、`infra/docker/wordpress/Dockerfile`の下記を変更してください。

```
FROM wordpress:latest
```

バージョンは下記より確認できます。

https://hub.docker.com/_/wordpress?tab=tags&page=1&ordering=last_updated

DB設定などを変えたい場合は `.env` を書き換えてみてください

```
cp .env.example .env
```

おまけ
------

メールの送信は[MailHog](https://github.com/mailhog/MailHog)を利用しているので

送信確認はhttp://localhost:8025/ にアクセスし確認することができます。
Googleの検索結果画面に表示される画像を設定する

#どうも7noteです。スマホ時のGoogle検索結果画面に表示される画像を設定する方法

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/04ecbb5f-7feb-91fd-b689-848b265205d6.png" width="300">

Googleで検索した際にたまに出てくる正方形の画像を任意の画像に設定する方法を解説していきます。

この正方形の画像の呼び方は**サムネイル(thumbnail)**と言います。思ったよりシンプルな名前。

## サムネイルの設定方法

**headタグに以下の一文を追加**し、画像を指定します。

```html
<meta name="thumbnail" content="(画像URL)" />
```


これでもしサムネイルが表示される場合は上で指定した画像が表示されるはずです。

## サムネイル設定の注意点

### ▼ 設定したから必ず表示されるわけではない

**設定しても表示されるとは限りません。**
もしサムネイルが表示される場合、この画像を表示してくださいというものです。

### ▼ 設定していないと勝手に画像が選ばれる

**サムネイル画像が設定がされていない場合は該当ページに設定されている画像が自動的に表示されます。**

そのため思わぬ画像が選ばれて、文字が見切れてしまう、なんてこともあるので設定しておいた方が無難でしょう。

設定する画像をわざわざ作らなくてもogp画像を用意しているサイトであればひとまずogp画像を設定しておくのも個人的にはアリかなと思います。

## まとめ

・headタグに1行追加。
・設定しても必ずサムネイルが表示されるわけではない。
・何かは設定しておく方が無難。ogp画像があれば取り急ぎogp画像を設定しておこう。

現在サムネイルが表示されるのはスマートフォンでの検索時だけです。
開発の優先度は低いですが、余裕があればしっかり設定しておきたいところですね。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
環境変数が更新されない場合の対処法

#ファイルの変更履歴が存在する場合の対処法
ファイルの変更履歴が存在する場合、つまり、Herokuにプッシュしたときから少しでもファイルに差分が存在する場合を考えます。この場合は通常通りコミットして、そのコミットをHerokuにプッシュすれば問題ありません。

```
% git add .
% git commit -m "後から見てわかりやすいコミット名"
```
その後、下記のコマンドを実行して、先ほど作成したコミットをHerokuへプッシュしましょう。

```
% git push heroku master
```
このように、環境変数をHerokuに設定するだけでは本番環境に反映されません。Herokuへpushすることではじめて本番環境に反映されます。
#ファイルの変更履歴が存在しない場合の対処法
続いて、ファイルの変更履歴が存在しない場合、つまり、特に変更するファイルもないがHerokuに設定した環境変数だけ本番環境に反映させたい場合です。
Herokuの仕様上、最新のコミット履歴が存在しない状態でgit push heroku masterコマンドを実行しても「Everything up-to-date（すでに最新の状態に更新されています）」と表示されます。

##空のコミットを生成する

```
% git commit --allow-empty -m "空のcommit" 
```
GitHub Desktopで空のコミット履歴が確認できれば成功です。
新しくコミットを生成することができたので、これで問題なくHerokuへプッシュすることができます。

```
% git push heroku master
```
#まとめ
　流れをおさらいすると、環境変数をHerokuの本番環境に反映させるためには、Herokuで環境変数を設定した上でプッシュする必要があります。しかし、環境変数を設定し忘れた状態でプッシュしてしまった場合、環境変数を設定した上でもう一度プッシュする必要があります。

　ここで1つ問題なのが、新しいコミットを生成しなければプッシュすることはできないということです。そこで空のコミットを生成してプッシュを行います。

　このように新しいコミット履歴がない場合は、空のコミット履歴を生成してプッシュするという方法があります。こちらは環境変数の設定漏れに後から気づいた場合などに有効的な手段です。
LeetCode日本語修行10日目- [368-最大整除部分集合]

###Largest Divisible Subset
#####参考：https://leetcode.com/problems/largest-divisible-subset/
###問題の内容:
正の整数集合nums、それぞれの要素が相異、この中に(answer[i], answer[j])の条件を満足するような最大の部分集合answerを返す。
**(answer[i], answer[j])の条件: 
   answer[i] % answer[j] == 0, または
   answer[j] % answer[i] == 0**
複数の解がある場合は、そのうちどちらも正しいです。
###例:
例1:
Input: nums = [1,2,3]
Output: [1,2]
Explanation: [1,3] is also accepted.

例2:
Input: nums = [1,2,4,8]
Output: [1,2,4,8]
###ヒント:
1 <= nums.length <= 1000
1 <= nums[i] <= 2 * 109
All the integers in nums are unique.

---
このような問題は、基本的DPを使います。今回は
必要の条件は、現在の要素の最大整除部分集合 maxSizeを貰います。
たとえ：
**1 2 4 6 8 9**
1: 1 ->1
2: 1,2  -> 2
4: 1,2,4 -> 3
6: 1,2,6 -> 3
8: 1,2,4,8 -> 4 
9: 1,9 -> 2
**1 2 4 6 8 9**
**1 2 3 3 4 2**
そして、最大の8の中に、必ず4,2,1を含めます。

```
if(nums[i] % nums[j]　== 0 && nums[j] % nums[k] == 0){
   nums[i] % nums[k] == 0
}
```
   
DPの形になりました。
貰ったmaxSizeを格納のdpArrayをトラバーサルして、maxSize対応のvalueを順番で渡す

```Kotlin
class Solution {
    fun largestDivisibleSubset(nums: IntArray): List<Int> {
        var size = nums.size
        var dpArray = IntArray(size){1}
        var maxSize = 1
        var maxValue = dpArray[0]

        nums.sort()

        for(i in 1 until size){
            for(j in 0 until i){
                if(nums[i] % nums[j] == 0){
                    dpArray[i] = Math.max(dpArray[i],dpArray[j]+1)
                }
            }
            if(dpArray[i] > maxSize){
                maxSize = dpArray[i]
                maxValue = nums[i]
            }
        }

        var answer: MutableList<Int> = mutableListOf()

        if(maxSize == 1){
            answer.add(nums[0])
            return answer
        }

        var index = size-1
        
        while(index >= 0 && maxSize > 0){
            if(dpArray[index] == maxSize && maxValue % nums[index] == 0){
                answer.add(nums[index])
                maxValue = nums[index]
                maxSize--
            }
            index--
        }
        return answer
    }
}

```
検索フォームの設置方法

まずは下記のようにフォームを記述。

```ruby
<%= form_with(url: search_pictures_path, local: true, method: :get, class: "search-form") do |form| %>
<%= form.text_field :keyword, placeholder: "キーワードを入れてね", class: "search-input" %>
<%= form.submit "検索", class: "search-btn" %>
<% end %>
```
続いてルーティングを設定。
全体から検索したいのでcollectionを使う。

```ruby
Rails.application.routes.draw do
  devise_for :users
  root to: "pictures#index"
  resources :pictures do
    resources :comments, only: :create
    collection do
      get 'search'
    end
  end
  resources :users, only: :show
end
```
次に検索のメソッドをモデルに定義。

```ruby
class Picture < ApplicationRecord
  has_one_attached :image
  belongs_to :user
  has_many :comments, dependent: :destroy

  validates :image, presence: true
  validates :title, presence: true
  validates :explanation, presence: true
  validates :impression, presence: true
  
  def self.search(search)
    if search != ""
      Picture.where('title LIKE(?)', "%#{search}%")
    else
      Picture.all
    end
  end
end
```
ここで使うのはwhereメソッドとLIKE句。
whereメソッドはモデルが使用できる、ActiveRecordメソッドの1つ。
書き方は「モデル.where('検索対象となるカラムを含む条件式')」
モデル.where(条件)のように、引数部分に条件を指定することで、テーブル内の「条件に一致したレコードのインスタンス」を配列の形で取得できる。
LIKE句は、曖昧（あいまい）な文字列の検索をするときに使用するもので、whereメソッドと同時に使う。
ちなみにelse　Picture.allは空で検索ボタンが押された時にずべてのデータが検索結果として表示されることを表している。

```ruby
  def search
    @pictures = Picture.search(params[:keyword])
  end
```
続いてコントローラーにsearchアクションを記述。

次に検索結果を表示するためのビューファイルを作成。
search.html.erbファイルをviews配下のディレクトリに作成し設置。

```ruby
<div class="contents row">
  <% @pictures.each do |picture| %>
    <%= render partial: "picture", locals: { picture: picture } %>
  <% end %>
</div>
```
検索結果がここに表示される。

これで一通りの実装が完了！
AWS EC2 インスタンスタイプについてまとめてみる

最近AWSの勉強を本格的に始めました。
その中で個人的に、EC2インスタンスタイプはイメージしにくいと感じたので、復習の意味も込めて、記事にしてみたいと思います。

今回はイメージ図を作って理解を深めました。

# AWSとは

>Amazon Web Servicesとは、Amazon.comにより提供されているクラウドコンピューティングサービスである。ウェブサービスと称しているが、ウェブサービスに限らない多種多様なインフラストラクチャーサービスを提供している。これらのサービスは全世界で22の地理的リージョンで提供されている。[^1]

簡単にいうとAmazonの提供しているインフラサービスですね。

# EC2とは

### 概要

EC2は

### Amazon Elastic Compute Cloud
の略称です。

それぞれの単語の頭文字をとって並べると「AECC」なので「EC2」なんですね。

## 特徴

+ 必要な時に必要なだけサーバーを使える
+ 使った分だけのコストを支払えばよい
+ 変更可能なインスタンス（簡単に言えば、OSを載せた仮想サーバーのこと）から性能を選択できる
+ 数分でサーバー調達起動まで
+ 世界(宇宙は?)を問わず使える
+ AMI(Amazon Machine Image)から幾つでも同じサーバを起動可能
+ セキュリティーグループでトラフィック制御できる
+ OSを管理者として操作可能
+ 様々な料金オプション

## メリット

+ 必要な時に必要なだけの量が使用できる
+ 事前にEC2インスタンスの数を予測する必要がない

つまり

サービス開発に集中できる!

# EC2インスタンスタイプをどう選べばいいのか

それは、EC2で何を実現しようとするかで変わってきます。

CPUにスポットを当てて使用したり、RAM（メモリー）を強化して使いたいといった、提供したいサービスのニーズに合わせて選択します。

※例えばこのように表記されます↓

### t2.micro

[ファミリー]t[世代]2.[サイズ]micro

ちなみにこのタイプは汎用型インスタンスタイプです。

このインスタンスタイプはかなり重要なのですが、覚えるのがちょっと大変です。
イメージ図にして覚えました。

# イメージ

まず、ファミリーの
C,M,T,X,Rの5種類を覚えれば十分です。

![スクリーンショット 2021-04-20 19.01.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1009976/f30556c3-c977-f093-30ce-e5708e5c1d8a.png)
(米印の表現はあくまでイメージです。)

ここでTタイプに注目しましょう。

Tタイプとは
M(Most scenario)と同様の汎用的な利用用途に選択できるインスタンスタイプです。

負荷がかかった時にCPUを多く利用したい時ってありませんか?
そこでこのTタイプが登場します。

CPUパフォーマンスがバーストする機能
Turbo機能を備えているのでTと表記するようです。

次に少し発展的なタイプです。

![スクリーンショット 2021-04-23 22.07.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1009976/97356b12-6663-a2a5-8113-afa71b7ffacd.png)

こちらもイメージですが、(米印の表現はあくまでイメージです。)

ストレージを強化したもの、高速なコンピュータ処理を強化したもの等を使用したい場合に選ばれるタイプです。

HDD,InputOutput,Dense(密集という意味で、磁気媒体などの記録密度的なイメージで覚えると良さそう)[^2]

GPU,FPGA(GPUや、FPSゲームに必要なGPU処理等のイメージで覚えると良さそう)


ある程度、実際のネーミングの語源に近づけて解説を頑張ってみてはいますが、もう少しイメージだけではなくて、正確な語源等が知りたい方は以下が参考になるかもしれません。

https://stackoverflow.com/questions/48235393/meaning-of-the-number-in-aws-instance-type-name


# サイズ

nano,micro,smallといった小さなリソースから選択できるので安価に利用できます。
このサイズは何のサイズなのかというと、実は要素がいくつもあります。
なので性能のレベルというイメージで良いです。

例えば、

CPU,メモリ、ネットワーク、ストレージ etc...

もちろんこれらは、EC2の最大の特徴である、Elastic（伸縮性）にサイズを変更できます。

# 世代
これは、バージョンですね。

最後に重要な点をまとめると。

+ インスタンスタイプはElastic（伸縮性）に柔軟に性能を変えられる。
+ そもそも性能予測をする必要がない。

# 最後に
AWSはその広範囲にわたる、様々なサービスを実現するために、本当に細かく分けられた機能をサービスとして展開しているため、たまにイメージしづらいことがありますが、自分のためのメモとして今後もまとめていきたい。

[^1]: 「Amazon Web Services」https://ja.wikipedia.org/wiki/Amazon_Web_Services

[^2]: 「(AWS初心者) EC2インスタンスタイプが覚えられない」https://qiita.com/feifo/items/38c97b41dfbe468c640e
【AWS】AWS Organizationsについて

#プログラミング勉強日記
2021年4月23日

#AWS Organizationsとは
　複数のAWSアカウントを利用している場合に統合管理ができる。IAMのアクセス管理を簡単に実施できるマネーシド型のサービス。
　AWS Organizationsでできることは以下の3点である。

- AWSアカウントをグループ化してポリシーを適用して一元的に管理することができる。
- コンソール・SDK・CLIでAWSアカウントを新規作成して作成内容をログで管理できる。
- 複数AWSアカウントの請求を一括化できる。


　アカウントの設定方法としては、AWSアカウントの中から管理アカウント(マスターアカウント)を選定する。メンバーアカウントは、管理アカウントから招待を承認するとメンバーアカウントとして登録される。<b管理アカウントでない限りはルートアカウントであっても>AWS Organizatinsを利用した組織的な管理を行うことはできない。</b>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/2e3fea2f-54ee-f716-aab6-f2efcd9fe4c7.png)


#管理の方法
　支払一括代行とアカウント全体管理の2つの方式がある。

##Consolidated Billing Only 
　支払一括代行のみを実施するときに選択する。AWSの費用請求をまとめられるAWSの機能の1つで、複数のアカウントの費用を1つにまとめて払うことができる。

##All Features
　支払一括代行も含めて組織内の複数アカウントを統制したいときに選択する。名前の通りすべての機能を管理する。
Drone CI: Docker Hub にログインしてイメージを Pull する

2020年11月から Docker Hub でログインなしの匿名ユーザからの Pull 回数には IP あたり上限(6 時間あたり 100 回まで)が設けられたため、以下のようなエラーになってしまう場合がある。

> Error response from daemon: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit

これを回避するため、ユーザー認証して Pull する。

参考)

- https://blog.nijohando.jp/post/2020/drone-pull-image-with-auth/

## 手順

### Docker Hub へのアクセストークンを発行する

 1. Docker Hub にログインする。

 1. Account Settings > Security > Access Tokens から「New Access Token」でアクセストークンを生成する。

 1. ユーザー名とアクセストークンを結合して Base64 化する。

    ```shell
    DOCKERHUB_USERNAME=(ユーザー名)
    DOCKERHUB_ACCESS_TOKEN=(アクセストークン)
    DOCKERHUB_AUTH=$(echo -n "${DOCKERHUB_USERNAME}:${DOCKERHUB_ACCESS_TOKEN}" | base64)
    ```

### .drone.yml に設定

参考) [Pulling Private Images](https://docs.drone.io/pipeline/docker/syntax/images/#pulling-private-images)

.drone.yml に image_pull_secrets を記述することで、docker pull 時の認証情報を指定する。(`dockerconfig` は Secret 名)

```yaml
image_pull_secrets:
  - dockerconfig
```

### Secrets に認証情報を設定

以下の内容で Secrets に登録する。

- SecretName: dockerconfig

- SecretValue

  ```json
  {
    "auths": {
      "https://index.docker.io/v1/": {
        "auth": "(発行したアクセストークン)"
      }
    }
  }
  ```

### Secrets に認証情報を設定 (Encrypted Secrets の場合)

参考) [Secrets - Encrypted](https://docs.drone.io/configure/secrets/encrypted/)

OSS 版の場合は Encrypted しか対応していないため、.drone.yml に暗号化して記述する。

 1. Drone で暗号化する。

    ```shell
    export DRONE_SERVER=https://drone.example.jp
    export DRONE_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    REPOSITORY_NAME=(設定先リポジトリ名)
    drone encrypt "${REPOSITORY_NAME}" "{\"auths\":{\"https://index.docker.io/v1/\":{\"auth\":\"${DOCKERHUB_AUTH}\"}}}"
    ```

 1. 暗号化したデータを .drone.yml の Secrets に追記する。

    ```yaml
    kind: secret
    name: dockerconfig
    data: (暗号化した認証情報)
    ```
date-fnsでのエラー対処方法

# はじめに
<!-- 発端や概要を記載 -->
date-fnsを使って月名を選択できるプログラミングを使っていたら、急にエラーが出てきて困ったのでその解決方法をメモ。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. エラーが起こった状況
1. 原因と解決に向けてした事
1. 別のエラーの出現
1. 最終的な解決

<!-- 各チャプター -->
<a id="#エラーが起こった状況"></a>
# エラーが起こった状況
```
$yarn add date-fns //でインストール
$yarn
$yarn start //で起動すると

RangeError: Format string contains an unescaped latin alphabet character `n`

```

今まで正常に動いていたのだがこのエラーが出るようになった。

<a id="#原因と解決に向けてした事"></a>
# 原因と解決に向けてした事

色々と調べたところdate-fnsのバージョンの問題とのこと。
バージョンを1.3.13にすればいいとのことだったので、バージョンを指定して入れ直した。

```
$yarn add date-fns@^1.3.13
```

<a id="#別のエラーの出現"></a>
# 別のエラーの出現

```
Module not found: Can't resolve 'date-fns/_lib/format/longFormatters'
```

先ほどのエラーは出てこなくなったが別のエラーが・・・

<a id="#最終的な解決"></a>
# 最終的な解決

```
$yarn add @date-io/date-fns@1.x date-fns
```

このコマンドで入れ直したところエラーが出なくなりました！
Drone CI: 別の IAM ロールで AWS にアップロード・デプロイする

Drone Server を EC2 で動かした場合にインスタンスロールに直接権限を持たせるのは避け、パイプライン内で必要に応じて別の IAM ロールに Switch Role する。

## IAM ロールの作成

Drone Server から Switch Role する IAM ロールの Trust Relationship に、インスタンスロールを追加する。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxx:role/xxxx"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

インスタンスロールには AssumeRole 権限を付与しておく。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::*:role/*",
            "Effect": "Allow"
        }
    ]
}
```

## Switch Role

### プラグインを使用する場合

[nodefortytwo/drone-aws-role-auth](https://github.com/nodefortytwo/drone-aws-role-auth) プラグインで AssumeRole をおこない、取得した認証情報をファイルに保存する。ロール権限が必要なステップで、そのファイルを読み込む。

```yaml
steps:
  # AssumeRole
  - name: awsrole
    image: nodefortytwo/drone-aws-role-auth
    settings:
      role: arn:aws:iam::xxxxxxxxxxxx:role/xxxx
      file: .awsrole_env

  # AWS へアップロード・デプロイするステップ
  - name: ...
    image: amazon/aws-cli
    commands:
      - . ./.awsrole_env
      - aws s3 cp ...
```

### プラグインを使用しない場合

以下のように自前でやっても良い。

```yaml
steps:
  - name: ...
    image: amazon/aws-cli
    commands:
      - |
        AWS_IAM_ROLE=arn:aws:iam::xxxxxxxxxxxx:role/xxxx
        CREDS=$(aws sts assume-role --duration-seconds 900 \
          --role-arn "$${AWS_IAM_ROLE}" \
          --role-session-name="${DRONE_REPO_OWNER}-${DRONE_REPO_NAME}")
        AWS_ACCESS_KEY_ID=$(echo "$${CREDS}" | jq -r '.Credentials.AccessKeyId')
        AWS_SECRET_ACCESS_KEY=$(echo "$${CREDS}" | jq -r '.Credentials.SecretAccessKey')
        AWS_SESSION_TOKEN=$(echo "$${CREDS}" | jq -r '.Credentials.SessionToken')
        export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
      - aws s3 cp ...
```
Azure仮想マシン(Linux)にデータディスクを追加して使用可能状態にする方法

## はじめに
Linuxマシン上で動くWebアプリケーション開発は何度も行ってきたが、データディスクの追加はやったことがなかったため、色々と調べてみました。

## バージョン確認
- azure-cli 2.21.0

## 1. リソースグループを作成する
今回用に新しくリソースグループを作成します。

```powershell
az group create --name myResourceGroup --location japaneast
```

## 2. 仮想マシンを作成する
仮想マシンを作成します。

```powershell
az vm create --resource-group myResourceGroup --name myVM --image UbuntuLTS --admin-username azureuser --generate-ssh-keys
```

## 3. データディスクを作成する
データディスクを作成します。容量は1GBとしました。
ディスクの作成と同時に仮想マシンへの接続（アタッチ）も行っています。

```powershell
az vm disk attach --resource-group myResourceGroup --vm-name myVM --name myDataDisk --new --size-gb 1
```

## 4. 仮想マシンにログインしてデータディスクの初期化する
仮想マシンにログインし、アタッチされたデータディスクを確認します。
まだマウントされていないことと、SIZE=1GBということから「sdc」であることが分かります。

```bash
azureuser@myVM:~$ lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda       8:0    0   30G  0 disk
├─sda1    8:1    0 29.9G  0 part /
├─sda14   8:14   0    4M  0 part
└─sda15   8:15   0  106M  0 part /boot/efi
sdb       8:16   0    7G  0 disk
└─sdb1    8:17   0    7G  0 part /mnt
sdc       8:32   0    1G  0 disk
sr0      11:0    1  628K  0 rom
```

今回はパーティション分割をせずにファイルシステム作成を行います。

```bash
azureuser@myVM:~$ sudo mkfs.ext4 /dev/sdc
mke2fs 1.44.1 (24-Mar-2018)
Discarding device blocks: done
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: d0bde097-6222-40df-b69c-67ef18ef7eab
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376

Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
```

## 5. データディスクをマウントする
ファイルシステムをマウンドするディレクトリを作成します。

```bash
azureuser@myVM:~$ sudo mkdir /mnt/datadrive
```

ファイルシステムをマウントします。

```bash
azureuser@myVM:~$ sudo mount /dev/sdc /mnt/datadrive
```

マウントされたことを確認します。

```bash
azureuser@myVM:/mnt/datadrive$ lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda       8:0    0   30G  0 disk
├─sda1    8:1    0 29.9G  0 part /
├─sda14   8:14   0    4M  0 part
└─sda15   8:15   0  106M  0 part /boot/efi
sdb       8:16   0    7G  0 disk
└─sdb1    8:17   0    7G  0 part /mnt
sdc       8:32   0    1G  0 disk /mnt/datadrive
sr0      11:0    1  628K  0 rom
```

これで、データディスクを使用できる状態になりました。
あとは、必要に応じてマウントの永続化（`/etc/fstab`）を行ってください。

## 参考ページ
[【Azure公式】Linux VM へのディスクの追加](https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/add-disk)
【Vue × Firebase】serverTimestamp()をjavascriptのデータ型で取得


#ServerTimestampとは

時間軸を全てサーバーに預けてしまうことによってモバイルの個体差によるずれを解消する機能です。

今回投稿した時間を投稿ページに反映させたく実装に至りました。

##データの追加

```javascript
postItem() {
      const id = firebase
        .firestore()
        .collection("posts")
        .doc().id;
      firebase
        .firestore()
        .collection("posts")
        .add({
          title: this.title,
          description: this.description,
          genre: this.genre,
          time: firebase.firestore.FieldValue.serverTimestamp(),
          id: id,
        });
```

Firestoreにデータを追加させる際に、今回はtimeという値を使って記載してみました。

```javascript
time: firebase.firestore.FieldValue.serverTimestamp(),
```

上記のように記載するだけで投稿時間を追加してくれます。

##データの取得

実は、serverTimestamp 自体は時刻情報を持ってなくて、
Firebase サーバー側でデータを保存する時にサーバーの時刻に置き換えるための目印でしかありません。

これをjavascriptのデータ型に置き換えて取得しなければなりません。

```javascript
{{ list.time.toDate().toLocaleString() }}
```
上記のように記載してあげることでjavascriptのデータ型で取得し、
「20xx / xx /xx xx:xx:xx」という形で時刻表示させる事が可能です。
【論文メモ】DeepLearningを用いた超解像手法/DeepSRの論文まとめ

#概要
論文メモシリーズの第2弾です。
今回読んだのは、[Video Super-Resolution via Deep Draft-Ensemble Learning (2015)](http://www.cse.cuhk.edu.hk/leojia/projects/DeepSR/)という論文で、動画像超解像処理に初めてDeep Learningを用いた手法です。
どちらかというと位置合わせ処理による超解像に近いような気はしますが、この位置合わせをDeep Learningで行ってる、みたいなイメージだと捉えやすい気がします。
それで、動画像にも適応させてみたらいい結果が出た、の方が近いかなぁと思います。(完全に自分の解釈ですが...)

ちなみにですが、後日このモデルを参考にして作成したプログラムの記事も書きます。
(SR Draftあたりは端折ったり色々変えているので参考になるかは不明ですが...)

実装してみた記事はこちら → [超解像手法/DeepSRを参考にした実装](https://qiita.com/morimoris/items/a844cc1dd595cbfebb66)

#目次
- 研究の出発点
- 高解像度化の流れ
  - SR Draftの生成
  - モデルの概要
- 結果
- 知見、貢献
- 参考文献

#1. 研究の出発点
・既存の超解像手法では、自然現象のような現実世界特有のシーンの超解像ができない。
・Deep Learningを用いた動画像超解像手法が存在しない。
(2021年現在では多数存在しているが、この論文がでた2015年はまだ存在していなかった。)
・SR Draft(SR画像の候補)とCNNを合わせることで高精度画像を出力できるのでは？という著者の考え。
(SR:Super-Resolution, 超解像のこと)

#2. 高解像度化の流れ
SR DraftとDeep Learningの組み合わせで高解像度化を行っている。
それぞれで新しいアルゴリズムを論文では提案しています。

##(1) SR Draftの生成
高解像度画像の候補をいくつか生成します。
詳細は論文に書いているので省略します。(Deep Learningに注目して本記事を書いているため)

##(2) モデルの概要
モデルの概要図は以下の図です。([論文](http://www.cse.cuhk.edu.hk/leojia/projects/DeepSR/)から引用)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/766947/bccf02a6-b13c-cce7-34c6-63c904e2c2a5.png)
入力枚数をN枚とすると、N-1枚がSR Draftで残りの1枚がBicubic法にて拡大した画像です。
出力は1枚の画像になります。

全部で4つの層から成り立っており、
最初の3層がConvolution層で、最後の1層が**Deconvolution層**です。

Convlution層では、入力したN枚の画像の位置合わせ処理を主に行っており、
Deconvolution層は、ノイズなどのVisual artifact(視覚的な異常？)を取り除く目的で使用されています。

#3. 結果
結果は、[論文](http://www.cse.cuhk.edu.hk/leojia/projects/DeepSR/)にもあるように既存手法より精細な画像を得ることができます。
結果例は以下の通りです。([論文](http://www.cse.cuhk.edu.hk/leojia/projects/DeepSR/)から引用)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/766947/6b115b9d-77b0-6f58-6d5f-6e9f6daa7cae.png)
左から、Bicubic法、bayesianSR, 本手法, 元画像となっています。
PSNRなどの画像評価手法による比較も論文では記載されいますので是非。

#4. 知見、貢献
・本手法は、精細な画像を得られる超解像手法である。
・実際に撮影された動画像でも精細な画像を得られたことから、動画像緒解像手法としても有効である。
・Deep Learningを用いた初めての動画像超解像手法である。

#5. 参考文献
・[矢谷流論文の読み方](https://iis-lab.org/misc/paperreading/)
　本記事の流れを書くために使用。
・[Video Super-Resolution via Deep Draft-Ensemble Learning](http://www.cse.cuhk.edu.hk/leojia/projects/DeepSR/)
　今回紹介した論文。
・[Qiita記事作成方法 初心者の備忘録](https://qiita.com/U-MA/items/996ae933ae94c5711883)
　まだMarkDown記法になれていないので使用。
TypeScriptで関数の引数に型変数とConditional Typesを使うテクニック

誰も書いてる人がいなかったので。執筆時点のTypeScriptのバージョンは4.2.3です。

以下の関数を見てください。

```ts
function f<T>(x: T extends string ? never : T) { return x }
```

このシグネチャが型レベルでどう動作するのか、ぱっと見でわかりますか？ 初めて見たとき筆者はわかりませんでした。しかし、ちょっと考えてみればなんとなく予想はつくでしょう。この引数`x`は、`string`型を受け取ろうとしているときだけ`never`型として振舞う（つまり`string`型だけを禁止する引数となる）という挙動をとります。このことの利点は、まだ真にTSに入ってはいない[Negated Types](https://github.com/microsoft/TypeScript/pull/29317)を（関数の引数の位置に限って）表現できる、ということももちろんですが、もっと重要なのは以下の点です。たとえば引数の代わりに返り値にConditional Typesを使用して:

```ts
function g<T>(x: T): T extends string ? never : T { return x as any }
```

このようにした場合、関数の**呼び出し時**にTSにエラーを吐かせることができません。その関数の`never`な返り値を実際に他のところで使おうとしたときに初めて型の異常が発覚します（しかも`never`型の値はどんな型の変数にも入れられるので、もしかしたら異常が発覚しないままかもしれません）。

```ts
f(42)
f("42") // Argument of type 'string' is not assignable to parameter of type 'never'.
g(42)
g("42") // NO ERROR HERE!!!!!!?!?!??!?!?!?!!?!!!!?!??!
```

これでは遅いと感じられる場合、引数の位置でConditional Typesを使うことを考えてください。

筆者がぱっと見でわからなかった原因は、型判断の結果がどう扱われるのかが、他の位置におけるそれと異なるからです。通常、`A extends B ? C : D`の`C`や`D`がそのまま型変数への束縛になることはありません。しかし引数の位置では、驚くべきことにそれが可能なのです。しかもこの束縛は式の外側の型変数に対して遡及的に起こっているのが面白いところです。

[TS Playground](https://www.typescriptlang.org/play?ts=4.2.3#code/GYVwdgxgLglg9mABMAPAFQHwAoAeAuRNRAUxymLABMBnRaqAJxjAHNEB+RMYgN2IcQE0ASkQBvRA2JQQDJDkQBfAFChIsBIhbps+QsKEkyFGnUbM2nbnwGGJUmXMQKAhrRdgAnkuWqsAFgAmYT8AIiDQkJYA4OVo8MDIoA)
C# 基礎文法一覧

この記事は数行で記述できる基礎的内容をまとまめました。
「他の言語と知識が混ざってC#での記述方法を忘れてしまった」というのは多々あることです。
そんな時にさっと知りたい情報のみを取得できるようにまとめました。

私自身がググって思い出した内容をまとめていますので随時アップデートし行く予定です。
もし、この記事に知りたい内容が載っていない場合はコメントで教えていただければ内容追加しますので教えていただければとお思います。


## 命名規則
変数名：キャメルケース
定数名：コンスタントケース
※個人的に採用しているものです。現場の書き方に合わせましょう。

## 配列
### 1Dim配列
#### 宣言
``` C# 
int[] iaArray = {"aa", "bb"};
// 長さだけわかっている場合
int[] iaArray = new int["配列の長さ"];
```
#### 最大最小
``` C# 
using System.Linq;
//~~~~~~~~~~~~~~~~~~
int iMaxNum = iaArray.Max(); //最大
int iMinNum = iaArray.Min(); //最小
```
### 2Dim配列
#### 宣言
``` C#
int iOne = 1;
int iTwo = 3;
int[,] a2Di_array = new int[iOne, iTwo];
```

## List
### 使用するusingディレクティブ
``` C#
using System.Collections.Generic;
```
### 宣言
``` C#
List<int> liListName = new List<int>();
```
### データの追加,削除
``` C#
//追加
liListName.Add("追加するデータ");

//特定の要素削除

//全て削除
liListName.Clear();
```
### ソート
``` C#
//昇順
liListName.Sort();

//降順（ラムダ式）
liListName.Sort((a, b) => b - a);
```
### 出力
``` C#
Console.WriteLine(liListName["出力する番号"]);
//ループで出力
foreach(var a in liListName){
  Console.WriteLine(a);
}
```

### 値が含まれているかどうか
``` C#
if(liListName.Contains("リストに含んでいるかどうか判定する値")){
  "含んでいるときの処理";
}
```


## 型変換
### int型 to Double型
``` C#
int iNum = 1;
double dNum = (double)iNum;
```
## 文字列の扱い
### 任意の番号の文字取得
``` C#
string sString = "あいうえお";
//1文字のみ（charで取得される）
sString (0)
//あ

//複数文字
sString.Substring("n番目（index番号）から", "m文字取得");
//例　１番目から２文字取得
sString.Substring(1, 2);
// いう
```

### 文字列の反転
``` C#
string sString = "あいうえお";
//パターン１
Console.WriteLine( string.Concat(sString .Reverse()) );　//おえういあ
//パターン２（LINQを使用しているため「using System.Linq」を読み込む）
Console.WriteLine( new string(sString.Reverse().ToArray()) );　//おえういあ
```

## 計算
### 小数点切り捨て
``` C#
Math.Floor(Double);
```
### 絶対値
Math.Abs(-5);
## for文
``` C#
for (long i = 0; i < 10; i++)
{
  //ループ内容
}
```

###ループ矯正終了
`break;`

## 正規表現
| 記号| 記号の説明 | 例 | 例の説明 |
|:-:|:-:|:-:|:-:|
| ^  | 行の先頭 | ^[0-9] | 行頭が数字 |
| $ | 行の末尾  | ^.{10}$  |  10文字の行 |
| &#124;|直前、直後どちらかのパターンに一致 | hoge&#124;piyo| hogeまたはpiyo|
|( )|カッコ内をグループ化。マッチした内容は参照可。|-|-|
```C#
var reg = new Regex("^(dream|dreamer|erase|eraser)+$");
if (reg.IsMatch(S))
{
    Console.WriteLine("YES");
}
```

## テンプレートリテラル
```C#
▼基本的な使い方
string Name = "hoge"
$"私の名前は{Name}です"
//私の名前はhogeです

▼「”」のエスケープ処理
$"私の名前は\"{Name}\"です"
//私の名前は"hoge"です

▼「{}」のエスケープ処理
$"私の名前は{{{Name}}}です"
//私の名前は{hoge}です

```
Python で変数が数値の配列かどうかチェックするメモ

## 背景

Python で, 変数が数値の配列であることを ensure したい.
できれば簡潔に.
期待しないデータだった場合は, エラーか例外が出れば OK.

## 方法

要素ごとにチェック

```py
l = [....]

assert all(isinstance(v, (int, float)) for v in l)
```

l が配列型でなければその時点で exception

### numpy を使う

numpy が使える場合は,

```
numpy.ndarray(l, float)
```

でいけます! 変換できなかったら exception でます.
(`l` が配列であるチェックを別途入れるとなお良いか)
バッチファイルで指定の文字が何文字目か調べる（ExcelのFIND関数相当）

Y子です。
趣向を変えて、Excelと同じ機能をバッチファイルで作ってみようと思います。
今回は、「`FIND`」関数を考えます。

# 文法
__`FIND(検索文字列, 対象, [開始位置])`__

# 概要
ExcelのFIND関数は、指定の文字（検索文字列）が、対象文字列の何文字目かを返します。
　`FIND("b", "abcde")`　→　`2`
　`FIND("cd", "abcde")`　→　`3`
開始位置をずらすこともできます。
　`FIND("cd", "abcde", 2)`　→　`2`

これと同じものを、バッチファイルで作ります。
_【[確認環境：Windows 10 Home (Bld. 19042.928)](https://qiita.com/koiwaiwaiko/items/ef2d457ae1e1a7c8b698 "Windows10のバージョンを確認・表記する")】_

# コード
```bat:find_like_excel.bat
@echo off
rem 検索文字列, 対象, [開始位置=1]
set find_text=%~1
set within_text=%~2
set start_num=%~3

rem 位置カウンタ初期化
set charpos=0
rem 文字位置カウント（サブルーチン実行）
call :find_like_excel "%find_text%" "%within_text%" "%start_num%"

rem 結果出力
if "%charpos%"=="0" (
  echo 見つかりません
) else (
  echo %charpos% 文字目
)
exit /b

rem ====サブルーチン====
rem 文字位置をカウントする
:find_like_excel
  setlocal

  rem 引数がない場合は終了する
  if "%~2"=="" (echo 引数がありません & pause & exit /b)

  rem 検索文字列, 対象, [開始位置=1]
  set find_text=%~1
  set within_text=%~2
  set start_num=%~3

  rem 開始位置の指定がない場合はデフォルト「1」
  if "%start_num%"=="" (set start_num=1)
  rem バッチファイルのデフォルトは「0」なので合わせる
  set /a start_num-=1

  rem 開始位置の調整
  call set within_text=%%within_text:~%start_num%%%

  rem 文字位置カウントのループ開始
  :label_find
  rem 位置カウンタ加算
  set /a charpos+=1

  rem 文字列がなくなったら終了
  if "%within_text%"=="" (
    set charpos=0
    goto :label_end
  )

  set length=0
  set str_tmp=%find_text%

  rem strlenループ開始
  :label_strlen
  rem 長さ加算
  set /a length+=1
  rem 1文字減らす
  set str_tmp=%str_tmp:~1%
  rem 文字列がなくなったら終了
  if not "%str_tmp%"=="" (goto :label_strlen)
  rem strlenループ終了

  rem 文字列が一致すれば終了
  call set str_tmp=%%within_text:~0,%length%%%
  if "%str_tmp%"=="%find_text%" (goto :label_end)

  rem 文字列がまだあれば、1文字減らしてループ
  set within_text=%within_text:~1%
  goto :label_find
  rem 文字位置カウントのループ終了

  :label_end
  endlocal && set charpos=%charpos%
exit /b
```

```:実行結果
> find_like_excel.bat b abcde
2 文字目

> find_like_excel.bat cd abcde
3 文字目

> find_like_excel.bat cd abcde 2
2 文字目
```

# 説明
`find_like_excel`サブルーチンに、処理をまとめました。
引数の「検索文字列」の文字数をカウントするために、__[バッチファイルで文字列長を取得する](https://qiita.com/koiwaiwaiko/items/bb3629937ce5642d2e2b)__ で作った`get_strlen`サブルーチンの処理を内包しています。

# おわりに
この関数を使って、また新しいことをしてみようと思います。

では！
AWS CLI で ES2 のインスタンス名をちょろっと json にしたい

# 目的
ちょっとやりたい事があって、その準備運動としてEc2インスタンスから必要な情報をjsonに加工してみた
# やってみた
cli コマンドを打つとダラダラとこんな感じ。。。。
欲しい情報はタグで設定されているインスタンス名とIDと状態

```
~ $ aws ec2 describe-instances
{
    "Reservations": [
        {
            "Groups": [],
            "Instances": [
                {
                    "AmiLaunchIndex": 0,
                    "ImageId": "ami-xxxxxxxxxx",
                    "InstanceId": "i-xxxxxxxxxx",
                    "InstanceType": "t2.micro",
                    "KeyName": "aws_key_xx",
                    "LaunchTime": "2021-04-23T10:51:23.000Z",
<略>
                    "State": {
                        "Code": 80,
                        "Name": "stopped"
                    },
<略>
                    "Tags": [
                        {
                            "Key": "env",
                            "Value": "DEV"
                        },
                        {
                            "Key": "Name",
                            "Value": "dev01"
                        }
                    ],
<略>
```

# こうなった
jqちょろっとしか使ってないから上手く書けなかったけど、jqの出力をまたjqに。。。
とりあえずできた、わーい

```
~ $ aws ec2 describe-instances | jq '.Reservations[].Instances[] | [{tag: .Tags[] , id: .InstanceId , state: .State}]' | jq '.[] | select(.tag.Key == "Name") | {name: .tag.Value ,id: .id ,state: .state.Name}'
{
  "name": "dev01",
  "id": "i-xxxxxxxxxx",
  "state": "stopped"
}
{
  "name": "dev02",
  "id": "i-yyyyyyyyyy",
  "state": "stopped"
}
```

# おまけ
jq のページ

https://stedolan.github.io/jq/tutorial/

https://stedolan.github.io/jq/manual/
【Vue.js】vue-swalを使ってアラートを実装


#vue-swalとは

「vue-swal」は、美しいアラートを実装するライブラリです。

ダイアログのステータスやボタン、テキスト入力をサポートしています。
シンプルな実装ながら、CSSをカスタマイズすること無く綺麗なアラートを実装できます。

#vue-swalの導入方法

以下のnpm、yarn、CDNを使ってインストールします。

- npm
 
```
npm install vue-swal
```

- yarn

```
yarn add vue-swal
```

- CDN

```html:CDN
<script src="https://unpkg.com/vue-swal"></script>
```


#導入手順

###1.ライブラリの取り込み

```javascript
import Vue from "vue";
import VueSwal from "vue-swal";
Vue.use(VueSwal);
```


###2.メソッドを設定

```javascript
export default {
  methods: {
   postItem() {
      const id = firebase.firestore().collection("posts").doc().id;
      firebase
        .firestore()
        .collection("posts")
        .add({
          title: this.title,
          description: this.description,
          genre: this.genre,
          time: firebase.firestore.FieldValue.serverTimestamp(),
          id: id,
        });
      this.$swal({
        title: "内容確認",
        text: "この内容で投稿しますか？",
        icon: "info",
        buttons: true,
        dangerMode: true,
      }).then((willDelete) => {
        if (willDelete) {
          this.$swal("投稿しました。", {
            icon: "success",
          });
          this.$router.go({ path: "/board", force: true });
        } else {
          this.$swal("キャンセルしました。");
        }
      });
    },
  },
}
```

「vue-swal」は4つのステータスをサポートしています。

- warning
- error 
- success 
- info

記述方法は下記を参照。

```javascript
.then((willDelete) => {
        if (willDelete) {
          this.$swal("投稿しました。", { //投稿された際のメッセージ
            icon: "success", //ここに記述。
          });
          this.$router.go({ path: "/board", force: true }); //投稿された場合、ページをリロード
        } else {
          this.$swal("キャンセルしました。"); //上記以外の場合のメッセージ
        }
      });
```
###3. テンプレートを準備

```html
<button class="post-btn" @click.prevent="postItem">投稿</button>
```



上記を追記することでメニュー外をクリックしたら閉じるようになったかと思います。
Cookieとセッション

HTTPの特徴として状態を保持しない**ステートレス（Stateless）**方式であることが挙げられる。HTTPでは、リクエスト/レスポンスの１往復のやりとりが完結された処理とみなされ、複数の処理を関連づける仕組みがない。
一方、ステートフルに対して状態を保持する**ステートフル（Stateful）**方式も存在する。この方式では、多数のクライアントの状態を１台のサーバーで保持し、それぞれの処理をすることになるため負担が大きくなる。
# Cookie（クッキー）
ステートレスなHTTPで、状態を保持し管理する場合、**Cookie(クッキー)**と呼ばれるデータを用いる。
## Cookieのやりとり
Webサーバーへ接続してきたWebブラウザに対し、コンテンツなどと一緒にWebブラウザに保存してもらいたい情報をCookieとして送る。
Webブラウザはそれを保存しておき、次にWebサーバーに接続する際に保存しておいたCookieを送信することで、Webサーバーは接続相手を識別することができる。
## メッセージヘッダーの利用
Cookieの送信にはメッセージヘッダーが利用される。WebサーバーはHTTPレスポンスに **「Set-Cookie」ヘッダー**を含めることでCookieを送信でき、WebブラウザはHTTPリクエストに **「Cookie」ヘッダー**を含めることで送信できる。「Set-Cookie」ヘッダーにはオプションでCookieの有効期限を設定したり、HTTPSのみを利用してCookieを送信する設定をしたりできる。
![Cookie.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999125/3d1b8932-8af6-d4b5-3a27-535d55e2c33e.jpeg)

### Cookieで利用されるヘッダーフィールド

| 名前         | 内容                      | 種別             |
| ---------- | ----------------------- | -------------- |
| Set-Cookie | 状態を保持・管理するための情報(Cookie) | レスポンスヘッダーフィールド |
| Cookie     | Webサーバーから受け取ったCookieの値  | リクエストヘッダーフィールド |

### Set-Cookieヘッダーフィールドに記述する内容

| 属性                 | 内容                        |
| ------------------ | ------------------------- |
| name=value         | Cookieにつける名前とその値(必須)      |
| expires=date       | Cookieの有効期限。              |
| max-age=seconds    | Cookieの残存時間を秒数で指定         |
| secure             | HTTPS通信時のみCookieを送信       |
| httponly           | JavaScriptからのCookieへの参照制限 |
| domain=Domain_Name | Cookieが利用されるドメイン名         |
| path=PATH          | Cookieが利用されるサーバー上のパス      |

各属性は「;」で区切って複数記述可能である。
## セッションCookie
**有効期限が設定されていないCookie**を**セッションクッキー**と呼び、Webブラウザが閉じられると同時に削除される。一方、**有効期限が設定されたCookie**は、Webブラウザが閉じられても削除されず、有効期限が来るまでWebブラウザ上に残り続ける。
CookieはWebブラウザの識別にも利用され、盗まれると他人になりすましされる可能性があるため、ショッピングサイトではセッションCookieがよく利用される。
# セッション
WebブラウザとWebサーバーのやりとりにおいて、一連の関連性のある処理の流れを**セッション**と呼ぶ。
例えばショッピングサイトで商品を買う際の「商品を選ぶ」「商品をカートに入れる」「カートの中身を確認する」「商品を購入する」といった処理の流れがセッションになる。
## セッションの管理
あるWebブラウザからの処理を関連性のある一連の処理(=セッション)として扱いたい場合は、Cookieを用いてセッション管理ができる。
セッション管理において、Webブラウザを識別するための情報を「**セッションID(SID)**」と呼ぶ。セッションIDはWebサーバーで生成され、Cookieに含めてWebブラウザに送信される。Webブラウザは次回以降、CookieにセッションIDを含めて処理を行うことでWebサーバーとのセッションを維持できる。
また、セッション内でのやりとりの内容(「何の商品を何個カートに入れた」など)は、「**セッションデータ**」としてWebサーバーに保存される。WebブラウザはセッションIDを用いてWebサーバーに保存されている自身のセッションデータを参照できる。
![セッション.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999125/3b3f621e-9455-b1a0-7df8-f0c51a764c94.jpeg)

# 参考
[イラスト図解式 この一冊で全部わかるWeb技術の基本](https://www.amazon.co.jp/gp/product/B06XNMMC9S/ref=ppx_yo_dt_b_d_asin_title_o05?ie=UTF8&psc=1)
【Python】ボリンジャーバンドによる売買手法をバックテストしてみた

以前，[MACDによる売買手法のバックテスト](https://qiita.com/Fujinoinvestor/items/780b138e441531860e60)を行ったので，今回はボリンジャーバンドによる売買をバックテストしてみました．

この記事では結果だけを記します．Pythonコードは以下の記事をご覧ください．

https://optrip.xyz/?p=3557

#手法の概要
今回は，株価がボリンジャーバンドを上回ったときに売り，ボリンジャーバンドを下回ったときに買う手法をバックテストします．
売り買い判定のボリンジャーバンドには，±2σと±3σのバンドを各々用い，それぞれの結果を示します．

例えば±3σのバンドを利用したBacktesting.pyの戦略クラスは，以下のように記述します．ボリンジャーバンドを形成するための移動平均線には25日線を使います．コード全文は[こちらの記事](https://optrip.xyz/?p=3557)末をご覧ください．

```python
class BBsigma(Strategy):
    n = 25 #移動平均日数
    nu = 3 #何σか
    nd = 3 #何σか
 
    def init(self):
        self.upper, self.lower = self.I(BB, self.data.Close, self.n, self.nu, self.nd)
 
    def next(self): # チャートデータの行ごとに呼び出される
         #+3σより大きいなら売り
        if self.data.Close > self.upper:
            self.position.close()
        #-3σより小さいなら買い
        elif self.data.Close < self.lower:
            self.buy() # 買い
```

また，バックテストは2018/1/1~2-21/4/22で行います．
最初の所持金は1000ドルとします．

#バックテストの結果

##Apple

![bokeh_plot (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1298289/a3f761ca-aa71-d7fd-9dc5-629f6bf4da38.png)

資産
±3σ：1000 → 1750(+75%)
±2σ：1000 → 1361(+36.1%)

##スチールダイナミクス

![bokeh_plot (18).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1298289/5eb9e73a-0d87-95ec-8684-ed1c2658ee17.png)

資産
±3σ：1000 → 1258(+25.8%)
±2σ：1000 → 754(-24.5%)

##IBM

![bokeh_plot (22).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1298289/46d34b7c-7c6b-fc4d-0307-de2608630034.png)

資産
±3σ：1000 → 1062(+6.2%)
±2σ：1000 → 1064(+6.4%)

#感想

±3σで判定する方が±2σで判定するよりも良い結果になりそうです．
また，[MACDでの売買](https://optrip.xyz/?p=3346)に比べると取引回数が少なく，儲けも小さくなりました．
ボリンジャーバンドは安定して利益が出そうですが，大きくリターンを出すのには向いていないのかもしれません．

バックテストを実行するコードはこちら ↓
https://optrip.xyz/?p=3557
クレジットカード決済用JavaScript準備 11　環境設定４


Tokenとは
-

PAYJPが発行します。
何のためにPAYJP側は必要なのか？これはクレジットカード会社はカード利用者のカード情報を持てないので別にトークンを発行してこのトークンを利用してカード利用者のカード情報等を検索して利用金額請求を行う。

Tokenは以下のjsのファイルが実行された時点(createToken)で発行される

```javascript:card.js
      Payjp.createToken(card, (status, response) => {
        if (status == 200) {
          const token = response.id;
          const renderDom = document.getElementById("charge-form");
          const tokenObj = `<input value=${token} name='token' type="hidden"> `;
          renderDom.insertAdjacentHTML("beforeend", tokenObj);
        }
```

SECRET＿KEYとPUBLIC_KEYについて
-

こちらは商品販売するサイトがクレジット決済代行サービスと取引を行う際の身分証明書となろもの。
【Ansible】変数結合時に()を入れないとどうなるのか検証してみた

### はじめに
<バージョン>
ansible 2.9.7
　Ansibleでは以下のようにリストを結合することが出来ますが、これをfilterにかけるときは
注意が必要みたいです。今回はuniqueフィルターで検証します。

```yaml:sample.yml
---
- name: list test
  hosts: localhost
  gather_facts: no
  vars:
    list1: ['a', 'b', 'c']
    list2: ['b', 'd', 'b']
  tasks:
    - name:
      debug:
        var: list1 + list2
```

### 1-1. 参考playbook1
　特に何も気にせず、uniqueフィルターにかけてみましょう。

```yaml:list_test_1.yml
---
- name: list test
  hosts: localhost
  gather_facts: no
  vars:
    list1: ['a', 'b', 'c']
    list2: ['b', 'd', 'b']
  tasks:
    - name:
      debug:
        var: list1 + list2 | unique
```

### 1-2. 実行結果1
　後半のlist2にしかフィルターがかかりませんでした。

```text:出力
  - a
  - b
  - c
  - b
  - d
```

### 2-1. 参考playbook2
　list1とlist2を( )で囲いましょう。

```yaml:list_test_2.yml
---
- name: list test
  hosts: localhost
  gather_facts: no
  vars:
    list1: ['a', 'b', 'c']
    list2: ['b', 'd', 'b']
  tasks:
    - name:
      debug:
        var: (list1 + list2) | unique
```

### 2-2. 実行結果2
　全体にフィルターがかかりました。

```text:出力
  - a
  - b
  - c
  - d
```

### 3-1. 参考playbook3
　ここまで来ると法則性がわかったと思いますが、念のためリストを3個にしてみます。

```yaml:list_test_3.yml
---
- name: list test
  hosts: localhost
  gather_facts: no
  vars:
    list1: ['a', 'b', 'c']
    list2: ['b', 'd', 'b']
    list3: ['a', 'd', 'd']
  tasks:
    - name:
      debug:
        var: list1 + list2 + list3 | unique
```

### 3-2. 実行結果3
　list3にだけfilterがかかりました。

```text:出力
  - a
  - b
  - c
  - b
  - d
  - b
  - a
  - d
```

### まとめ
　( )をつけずに変数の結合結果をフィルターに渡すと、最後の変数にだけfilterがかかるので注意しましょう。

### 参考記事
[変数文字列を連結する適切な方法](https://www.it-swarm-ja.com/ja/ansible/%e5%a4%89%e6%95%b0%e6%96%87%e5%ad%97%e5%88%97%e3%82%92%e9%80%a3%e7%b5%90%e3%81%99%e3%82%8b%e9%81%a9%e5%88%87%e3%81%aa%e6%96%b9%e6%b3%95/1054843570/)
ファイルをS3にアップロードするwebサイトをheroku上に作った。

スマホとか含めクライアント問わずアップロードしたファイルを、ローカルサーバに取り込む必要があったので、S3を使った忘備録です。

heroku上へのwebアプリの構築法は下記を参考にしてください。
[twilioとSendGridとherokuでキャリアメール代替プッシュ通知](https://qiita.com/kamotsuru/items/358f0e6f3d68ba4fc322)

### herokuでflaskアプリを実行するための環境変数設定

```
(venv)$heroku config:set FLASK_APP=upload.py
(venv)$heroku config:set FLASK_CONFIG=heroku
```

### AWS S3にアクセスするための環境変数設定
S3のバケット名と、IAMで、ユーザ作って、security credentialsで作ったaccess key

```
(venv)$heroku config:set S3BUCKET=S3バケット名
(venv)$heroku config:set AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx
(venv)$heroku config:set AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

### webページのbasic認証パスワードを環境変数で設定
ユーザ名はソースコードの中に埋め殺し(user)

```
(venv)$heroku config:set USER_PW=xxxxxxxx
```

### ソースコード他

```requirements.txt
boto==2.49.0
Click==7.0
Flask==1.1.1
Flask-HTTPAuth==3.3.0
gunicorn==19.9.0
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
Werkzeug==0.16.0
```

Procfile

```
web: gunicorn upload:app --timeout 15 --keep-alive 5 --log-level debug
```

ソースコード

```upload.py
from flask import Flask, render_template, request, jsonify
from werkzeug import secure_filename
from flask_httpauth import HTTPDigestAuth
import boto
import os

'''
アプリコンストラクタ
'''
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'

'''
Digest認証
'''
auth = HTTPDigestAuth()

users = {
  "user": os.environ.get('USER_PW')
}

@auth.get_password
def get_password(username):
  if username in users:
    return users.get(username)
  return False

@auth.error_handler
def auth_error():
  response = jsonify({'error': 'unauthorized', 'message': 'Invalid credentials'}
)
  response.status_code = 401
  return response

'''
View設定
'''
@app.route('/upload')
@auth.login_required
def upload():
   return render_template('upload.html')

@app.route('/uploader', methods = ['GET', 'POST'])
def uploader():
   if request.method == 'POST':
      aws_access_key = os.environ.get('AWS_ACCESS_KEY_ID')
      aws_secret_access_key = os.environ.get('AWS_SECRET_ACCESS_KEY')
      s3bucket = os.environ.get('S3BUCKET')
      f = request.files['file']
      s3 = boto.connect_s3(aws_access_key, aws_secret_access_key)
      bucket = s3.get_bucket(s3bucket)
      key = bucket.new_key(secure_filename(f.filename))
      key.set_contents_from_file(f) 
      return 'file uploaded successfully'

if __name__ == '__main__':
   app.run(host='0.0.0.0', debug=True)
```

webページテンプレート

```templates/upload.html
<html>
   <body>
      <form action = "/uploader" method = "POST" enctype = "multipart/form-data">
         <input type = "file" name = "file" />
         <input type = "submit"/>
      </form>
   </body>
</html>
```

### アップロード

例えばiPhoneで上記で構築した`https://xxxxxxx-xxxxxx-xxxxxx.herokuapp.com/upload`にアクセスすると、下記左のように認証して、右(Choose Fileを押下後)のようなシンプルな画面でファイル選択して、アップロードできる。
![upload.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117100/283532ec-67fc-08f1-45a9-414f71fc0905.jpeg)

### ローカルサーバでs3をマウント
上記webページから放り込んだファイルがs3fsでローカルにマウントできる。

```
sudo s3fs s3バケット名 /home/pi/s3fs_from/ -o allow_other -o uid=1000 -o gid=1000
```