OmniAICreator/Qiita-1.07M huggingface dataset:
webを支える技術　web概論編

# web概論

![web_support.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/978289/d438d118-3aac-ac9d-db3f-03ed3e4bc97d.jpeg) {.border}

インターン先でこれを読んでいるので、アウトプットとしてここにまとめておきます。
後世の方の役に立てたら、幸いここに極まれりです。（は？）


# webの用途
- webサイト
- ユーザーインターフェースとしてのweb
- プログラム用APIとしてのweb


# webを支えている技術
- HTTP
- URI
- HTML

![web.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/978289/f6c0c2bd-cde2-07d4-d849-29031b86681e.png)

## HTTP 
Hypertext Transfer Protocolの略。
これを使うことで、**情報を取得**することができる。

## URI 
Uniform Resource Identiferの略。
これを使うことで、**情報を指し示す**ことができる。

## HTML
Hypertext Markup Languageの略。
XMLをもとにした汎用な、**情報を表現する**文書フォーマット。

# webの側面
情報システムとしてみると、

- **ハイパーメディアシステム**
- **分散システム**

の二つの側面がある。

## ハイパーメディア
ハイパーメディアとは、テキストや画像、音声、映像など様々なメディアをハイパーリンクで結びつけて構成したシステム

ハイパーメディア以前のメディア、書籍や映画は線形的に先頭から順に読んだり視聴したりするのに対し、

ハイパーメディアはユーザが自分でリンクを選択して情報を取得することができる

## 分散システム
複数のコンピュータを組み合わせて処理を分散させる形式のことを「分散システム」と呼ぶ。

複数のコンピュータ（＝サーバ）で処理することで１台では処理が難しいものも効率的に処理することができる。

webは世界中に配置されたサーバに世界中のブラウザがアクセスする分散システムである。

分散システムとしてのwebが特徴的なのはプロトコルがシンプルな点だ。
CMakeの使い方メモ～コマンドのみ～

1. まず、プロジェクトのフォルダを作成
2. そこに、CMakeLists.txtっていうファイルを作成

3. 下記でbuildディレクトリを作成し、buildディレクトリに移動

```
mkdir build
cd build
```
下記でReleaseモードでConfigure&Generate

```
cmake .. -DCMAKE_BUILD_TYPE=Release
```

最後にbuild

```
cmake --build
```
[memo]deviseの導入方法

##deviseの導入手順

```
# Gemfile
% gem 'devise'

#ターミナル
% bundle install

# deviseの設定ファイルを作成
% rails g devise:install

# deviseコマンドでUserモデルを作成
% rails g devise user

# テーブルの設計を確認しマイグレーションファイルへ追記
% rails db:migrate
```

deviseでログイン機能を実装すると、ログイン/サインアップ画面が自動的に生成されますがビューファイルとしては生成されません。
これは、deviseのGem内に存在するビューファイルを読み込んでいるためです。

deviseのビューファイルに変更を加えるためには、deviseのコマンドを利用して、ビューファイルを生成する必要があります。

```
# deviseのコマンドで、devise用のビューファイルを生成
# deviseに用意されたビューファイルをコピーし、app/viewsの配下に配置してくれるコマンド
% rails g devise:views
```
サインアップ画面は``app/views/devise/registrations/new.html.erb``

```
# ルーティングを調べる
% rails routes

％ 結果
 Prefix Verb   URI Pattern                                                                              Controller#Action
                     new_user_session GET    /users/sign_in(.:format)                                                            devise/sessions#new
                         user_session POST   /users/sign_in(.:format)                                                            devise/sessions#create
                 destroy_user_session DELETE /users/sign_out(.:format)                                                           devise/sessions#destroy
                    new_user_password GET    /users/password/new(.:format)                                                       devise/passwords#new
                   edit_user_password GET    /users/password/edit(.:format)                                                      devise/passwords#edit
                        user_password PATCH  /users/password(.:format)                                                           devise/passwords#update

~省略~
```
new から create へ form に入力された内容を渡す(user_session POST)ため、ヘルパーメソッドのパスは下記のようになる。

```:サインアップ画面：app/views/devise/registrations/new.html.erb
<%= form_with model: @user, url: user_registration_path, id: 'new_user', class: 'new_user', local: true do |f| %>
```


ログイン画面は``app/views/devise/sessions/new.html.erb``

```:ログイン画面：app/views/devise/sessions/new.html.erb
<%= form_with model: @user, url: user_session_path, id: 'new_user', class: 'new_user', local: true do |f| %>

```

サインアップ時に入力する情報はパラメーターとしてサーバーに送信されます。
不要な情報をうけとらないようにパラメーターを記述する必要があります。
また、デフォルトで備わってない値を送信（ここでは:nickname）も下記の方法です。
deviseのコントローラーにストロングパラメーターを反映する方法

```ruby:devise_parameter_sanitizerメソッド
private
def configure_permitted_parameters  # メソッド名は慣習
  # deviseのUserモデルにパラメーターを許可
  devise_parameter_sanitizer.permit(:deviseの処理名, keys: [:許可するキー])
end

# 例
private
def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
end

# 処理名
:sign_in	サインイン（ログイン）の処理を行うとき
:sign_up	サインアップ（新規登録）の処理を行うとき
:account_update	アカウント情報更新の処理を行うとき
```

```ruby:記述箇所：すべてのコントローラーが継承しているapplication_controller.rb
# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  private
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
  end
end

```
「TRAVEL×YOU (トラベリュー)」解説

#はじめに
スクールの個人開発でWebアプリを作りました。
アプリ名は「TRAVEL×YOU (トラベリュー)」です。
色々な思いを込めて作ったアプリなので、この機会に「TRAVEL×YOU」についてQiitaで解説したいと思います。

![works_image2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059683/84631cd0-a571-4e59-adcc-5f344b7ee13e.jpeg)

http://18.179.42.2/

#TRAVEL×YOUとは
今は、コロナウィルスで海外旅行ができないですが、これを機に今までの旅を振り返ってみて、旅先での今までの色々な経験、トラブルをシェアすることができ、インプットした情報はコロナウィルスが終息した後の旅に役立てることができます。旅をより楽しいものにするツールです。


###TRAVEL×YOUを作ろうと思った経緯
スクールでのチーム開発中、チーム開発の後に個人開発をするということを聞き、個人開発のテーマについて何となく考え始めました。どうせだったら自分の好きなことについてのアプリにしたいと思いました。

そこで浮かび上がったのが「旅行」です。

僕はコロナウィルスの流行直前、去年の3月の中旬までデンマークで国境が封鎖されるまでヨーロッパに1ヶ月ほど旅行していました。海外旅行が大好きなのです。

以前からネット上で、自分が訪れた国を一覧で見れるようにしたいと思っていました。そこから着想し、SNSのように画像投稿ができたり、旅先でのトラブルをシェアできたり、知恵袋のように旅行に関する質問ができたりなどインタラクティブなアイディアが次々と思い浮かびました。

###名前の由来

アプリの名前はすぐに思いつきました。×をアプリの名前に入れたくて、旅行=TRAVEL、それに何をかけようと思ったところ、YOUが出てきました。理由は分かりません(笑)

名前の読み方は、あの名曲「ロード」を生み出した虎舞竜(とらぶりゅう)に掛けています(笑)

###コンセプト

####旅とあなたをつなぐプラットフォーム

遠い存在になってしまった旅行(TRAVEL)があなた(YOU)にとって身近なものになってほしいとの願いが込められています。


###ターゲット
海外旅行が好きな全世代、バックパッカー、一人旅が好きな人


#主な機能

###OUR TRAVELS

今までの海外旅行で撮った写真最大5枚(カバー写真を含む)と旅行記を投稿できます。
旅版Instagramのようなものです。

###TROUBLE×YOU

こちらはTRAVELではなくTROUBLEです。単語が似ているので、掛けました笑

画像付きで旅先で起こったトラブル、その解決方法を投稿できます。

旅はトラブルがつきものです。一人旅が好きな人やバックパッカーは一人で色んなトラブルを乗り越えてきました。それをただの経験としてではなく、今後旅する誰かに役立てることができます。

###Q & A
旅行する予定の国や都市に関する質問を投稿したり、回答したりすることができます。 
旅行版知恵袋のようなものです。

###MY TRAVELS (マイページ)
今までした全ての投稿の表示、編集ができます。
また、今まで訪れた国と行った国がピン留めされた地図が表示されます。

###各機能
・ユーザー関連
新規登録 / ログイン機能
ゲストログイン機能
ユーザーごとのページ

・投稿関連
画像投稿機能 / テキスト投稿機能
投稿編集機能

#技術・環境
###フロントエンド
・Bootstrap 4.5
・HTML / CSS
・Java Script / jQuery

###バックエンド
・PHP 7.3.24
・Laravel 7.30.4

###開発環境
・MAMP
・MySQL 5.7.32

###本番環境
・AWS (EC2)

#工夫した点
###UI / UX
・ユーザーが利用しやすいインターフェースを心がけてデザインしました。
・マイページの画面いっぱい使って、色んな情報を一度に見れるように工夫しました。
###環境・技術
・Bootstrapを意識的に活用しました。
・Laravelの仕組みを理解しながら、機能を実装しました。

#苦労した点
・画像投稿機能
・全ての投稿したデータを一つのページに表示させること

#今後実装したい機能
・コメント機能
・いいね機能
・APIを使った訪れた国の地図表示機能
・SNS連携機能
・国、カテゴリーごとのページ、検索機能
・Dockerを使って開発

#さいごに
「TRAVEL×YOU」はポートフォリオだけに留まらず、沢山の人に使っていただきたいアプリです。今後、さらにたくさんの機能を実装して、アプリの精度をあげていつかサービス化できたらと思っています。
[memo]ログインしているかどうかの判定


##user_signed_in?メソッド
ログインしているかどうかの判定を行うdeviseのメソッド

例：viewでログインしているときとそうでないときで表示を分ける場合に使う

```:app/views/layouts/application.html.erb
<% if user_signed_in? %>
　<div class="user_nav grid-6">
　　<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
　　<%= link_to "投稿する", new_tweet_path, class: "post" %>
　</div>
<% else %>
　<div class="grid-6">
　　<%= link_to "ログイン", new_user_session_path, class: "post" %>
　　<%= link_to "新規登録", new_user_registration_path, class: "post" %>
　</div>
<% end %>
```

##redirect_toメソッド＋unlessの条件分岐＋exceptオプション
例：未ログイン状態のユーザーを転送させる場合に使用

```ruby:controllerに記述
class TweetsController < ApplicationController
  before_action :move_to_index, except: [:index, :show]　#index,showアクションを除く

  def index
    @tweets = Tweet.all
  end

  def new
    @tweet = Tweet.new
  end

〜〜省略〜〜

  def show
  end

  private

〜〜省略〜〜

  def move_to_index
    unless user_signed_in? #userがサインインしてない場合
      redirect_to action: :index
    end
  end
end

unless 条件式
  # 条件式がfalseのときに実行する処理
end 
```
今週は、unity1weekが開催されてますよーーー


今週は、　unity1weekが　開かれていますね。

ご存知のとおり、　1週間でゲームを作っていく

ゲームジャムのイベントです。



Unity1weekでは、　毎回　お題が出ていて

そのお題をもとに、ゲームを作っていきます。

今回のお題は、　回です。

回として、思いつくのはやはり回転系のゲームですので

このタイプのゲームがきっと多いと思いますね。


あとは、　回復なんかもありですね。


このように、　回に関することなら何でもOKって感じになります。

私もどちらかといえば、　プランナータイプなので

アイデアを練るだけでも楽しいのですが。

時間が1週間しかありませんからね。

そんな猶予なことは言ってられないです。

できるなら、アイデアは48時間以内に決めたほうがいいです。

それ以上だと、　ゲームを作る時間がなくなりますからね。

そのへんの時間配分を間違えてしまうと、　まじで間に合わなくなるのよ。



ゲームジャムのモットーは

面白いゲームを作ることよりも、　時間をちゃんと守ることですから

時間は厳守です。　　　それを守ってこそのゲームジャムなのですよ。







ＰＳ　

[ゲームジャムのコツはこちらに書きましたので](https://unitymaster2.com/unity1week/)
【circleCI】を使って、githubと連携させ、テストを自動化する

##初めに
転職に向けてPF作成中。そんな中、circleCI で良い方法を見つけたので共有。

##環境
macOS
ruby2.6.6
rails6.1.3
Docker20.10.2

##背景
circleCIを自分のPFに導入しようとしてDocker入門を頼りに進めていたところ、
どうしても行き詰まり、何か良い方法はないかと検索していた。
そこで、Docker-composeとcircleCIを連携させている記事に出会い、
無事に導入出来たので紹介したくなりました。

##結論

```config.yml

version: 2
jobs:
  build:
    #Docker-composeが仮想済のマシーンをpull
    machine:
      image: circleci/classic:edge #最新のDocker環境で使えるようになる
    steps:
      - checkout
      - run:
          name: Dockerコンテナのビルド
          command: docker-compose build
      - run:
          name: Dockerコンテナの起動
          command: docker-compose up -d
      - run:
          name: "10秒待機させる"
          command: sleep 10
      - run:
          name: データベースの作成
          command: docker-compose run web rails db:create RAILS_ENV=test
      - run:
          name: データベースのセットアップ
          command: docker-compose run web rails db:migrate RAILS_ENV=test
      - run:
          name: Rspecテスト実行
          command: docker-compose run web bundle exec bin/rspec
      - run:
          name: rubocop実行
          command: docker-compose run web bundle exec rubocop
      - run:
          name: Dockerコンテナの停止
          command: docker-compose down
```
【Kubernetes】Pod内のnginxにローカルのhtmlファイルを表示させる

### はじめに
<バージョン>
minikube: v1.9.2

　前回の記事、[【AWS】Docker内のコンテナにアクセスしたい](https://qiita.com/masa2223/items/a6492aeee5c83a1f8c5b)ではdockerコマンドで
httpdにアクセスしましたが、今回はそれをKubernetesで行ってみます。
やりたいこととしては、
（1）ローカルストレージ「/data/html」に、Pod内にあるnginxのディレクトリ
　 「/usr/share/nginx/html」をマウントする。
（2）ローカルの「/data/html/index.html」をnginxに表示させる。
※今回は、ローカルPCにVMを作成して作業しています（AWSに構築していません）


### 1.マニフェストファイル作成
　まずはホームディレクトリ（任意）に以下のマニフェストファイルを作成します。
**ポイント**
（1）docker imageを[dockerhub](https://hub.docker.com/_/nginx)から持ってくる。
（2）ローカルストレージ「/data/html」に、Pod内にあるnginxのディレクトリ
　 「/usr/share/nginx/html」をマウントする。
（3）serviceの種類をNodePortにして、外部からの接続ポート（今回は30000番）を指定する。

```yaml:nginx-test.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: web
    env: test
spec:
  containers:
  - name: nginx
    image: nginx:1.17.2-alpine    # ポイント(1)
    volumeMounts:
    - name: storage
      mountPath: /usr/share/nginx/html    # ポイント(2)
  volumes:
  - name: storage
    hostPath:
      path: "/data/html"    # ポイント(2)
      type: Directory

---
apiVersion: v1
kind: Service
metadata:
  name: web-test
spec:
  type: NodePort     # ポイント(3)
  selector:
    app: web
    env: test
  ports:
  - port: 80
    nodePort: 30000     # ポイント(3)

```

### 2. htmlファイル作成
　以下の手順でローカルにindex.htmlを作成します。

```text
mkdir -p /data/html
echo "hello world!" > /data/html/index.html
```

### 3. nginxの起動
まずは「kubectl apply」のコマンドでnginxを起動させます。
-f で作成したマニフェストファイルを指定します。

```text
kubectl apply -f nginx-test.yml
```

nginxを起動させたら、「kubectl get」コマンドで状態確認をします。

```text
[root@localhost ~]# kubectl get -f nginx-test.yml 
NAME        READY   STATUS    RESTARTS   AGE
pod/nginx   1/1     Running   0          3s    # STATUSがRunningになっている

NAME               TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/web-test   NodePort   <ip-addr>   <none>        80:30000/TCP   3s    # ポートフォワーディングが適用されている
```

実際にPodにアクセスしてマウントされているか確認しましょう。
コマンドは「kubectl exec -it pod/<Pod名> sh」です。

```text
[root@localhost ~]# kubectl exec -it pod/nginx sh
/ # cd /usr/share/nginx/html
/usr/share/nginx/html # ls
index.html      　　　　　　　　　# ファイルがマウントされていることを確認
/usr/share/nginx/html # cat index.html
hello world!                    # ファイルの中身が正しいことを確認
/usr/share/nginx/html # exit    # exitでPodから抜ける
[root@localhost ~]# 
```

### 4. webサイトへアクセス
　ブラウザを起動してアクセスし、「hello world!」が表示されたら完了です。
URLは「http://<作業端末ののIPアドレス>:30000」です。
ちなみに、ローカルでも確認することが可能です。

```text
[root@localhost ~]# curl http://localhost:30000
hello world!
```


### 参考資料
[dockerhub - nginx](https://hub.docker.com/_/nginx)
[Kubernetes道場 9日目 - Serviceについて](https://cstoku.dev/posts/2018/k8sdojo-09/)
同じコンポーネントでページ遷移するときはbeforeRouteUpdate

#概要
`コンポーネントA(/mypage/1)→コンポーネントA(/mypage/2)`にページ遷移する場合に、
再描画されなくて困っていたのですが、beforeRouteUpdateを使うことで解決できました。

#実装
公式を参考に実装しました。
[公式サイト](https://router.vuejs.org/ja/guide/advanced/navigation-guards.html#%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E3%83%93%E3%83%95%E3%82%A9%E3%83%BC%E3%82%AC%E3%83%BC%E3%83%89)

##使い方
```.js
beforeRouteUpdate (to, from, next) {
  // `this` を使用
  this.name = to.params.name
  next()
}
```

to:ページ遷移先の情報
from:現在のルート情報

##toの中身を見てみる

```.js
beforeRouteUpdate (to, from, next) {
  console.log(to)
}

//結果
fullPath: "/mypage/2"
hash: ""
matched: Array(2)
  ...
params:
    userId: 2
path: "/mypage/2"
```

今回はparamsが変更された場合に遷移したいので、params.userIdを使用してページ遷移を実現します。

##Vue
```.vue
<script>
export default{
  props: {
    userId: String //ユーザーID
  },
  mounted() {
    this.$store.dispatch('page/getUser', this.userId)
  },
  beforeRouteUpdate(to, from, next){
    const name = to.params.userId
    this.$store.dispatch('page/getUser', name)
    next()
  }
}
</script>
```
`beforeRouteUpdate`
to.params.userIdが変更されるごとに、

    this.$store.dispatch('page/getUser', name)

が呼び出され、

    next()

でページの遷移を行います。


##Store
```store/page.js
const state = {
  data: '',
}
const getters = {
  data: state => state.data ? state.data : '',
}
const mutations = {
  setData(state, data){
    state.data = data
  },
}
const actions ={
  async getUser({commit}, user_id) {
    await axios.get('/api/user', {
      params: {
        user_id: user_id
      }
    }).then(res=>{
      commit('setData', res.data)
    }) 
  },
}
export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
```
ユーザー情報を取得するだけのAPIになっています。


#参考文献
[Vue Routerでのページネーションライフサイクル](https://qiita.com/kiyc/items/42636f3e647dd9c25342)
laravel6 CentOS7 Apache ドキュメントルートを変更しApacheを再起動したらエラーが出た

# 目的

- CentOS7のPCにApacheを入れてlaravelのためにドキュメントルートを修正し、Apacheを再起動したらしょうもないミスでエラーを出したので戒めとしてまとめる

# 原因

- laravelのアプリケーションディレクトリの位置を間違えていた。

# 解決までの敬意

1. とあるディレクトリで`$ laravel new test`というコマンドを実行してlaravelアプリを作成した。
1. Apacheの設定ファイルを開き、ドキュメントルートを修正した。
1. `$ sudo service httpd restart`を実行してApacheを再起動した。
1. エラーが発生した。詳細情報がほしかったので`$ systemctl status httpd.service`を実行した。
1. 「DocumentRoot '/var/www/test/public' is not a directory, or is not readablet」というエラーが出力されていた。
1. `$ sudo yum remove httpd`を実行してApacheを一旦削除した。
1. `$ sudo yum install httpd`を実行してApacheを再インストールした。
1. 依存性の問題からPHPのパッケージも削除されてしまったためyumを用いてインストールした。
1. `$ sudo service httpd start`を実行してApacheの起動を試みたが同じエラーが出て起動しない。
1. chownコマンドを用いてlaravelのアプリ名ディレクトリ配下のオーナーをApacheに変更した。
1. `$ sudo service httpd start`を実行してApacheの起動を試みたが同じエラーが出て起動しない。
1. laravelのアプリ名ディレクトリの設置場所（作成場所）に誤りがあった。
1. `/var/www/`直下で`$ laravel new test`を実行しないといけなかったのに、`/etc/www`直下で`$ laravel new test`を実行していた。
SOLID原則のISPまとめ

# ISPとは
ISP（Interface Segregation Principle：インターフェース分離の原則）とは、
***「ドメインが異なるメソッドをひとつのインターフェースに混在させ、利用者が使用しないメソッドへの依存を強制させてはいけない」***
というルール

ひとつのインターフェースにドメインがバラバラなメソッドを詰め込んでしてしまうと、必要の無いメソッドの実装を強制されたり、本来関係ないところと依存関係が生じたりしてしまう。
そのため、ISPに違反した実装はバグを誘発させたり保守性を悪化させたりする。

すなわち、インターフェースはドメインごとに分割して肥大化させるのはやめましょうという考え方。

# 具体例
ISPに則り、管理者が商品を出品して、それをユーザーが購入するECサイトを考えると次のようになる。

```python
from abc import ABCMeta  
from abc import abstractmethod  

# 管理者インターフェース
class administrator_interface(metaclass = ABCMeta):
    @abstractmethod
    def register(self):
        pass # 商品の登録
    @abstractmethod
    def delete(self):
        pass # 商品の削除

# ユーザーインターフェース
class user_interface(metaclass = ABCMeta):
    @abstractmethod
    def buy(self):
        pass # 商品の購入
```

管理者インターフェースとユーザーインターフェースを設けることで、それぞれのドメインで必要なメソッドだけ定義できていることがわかる。
もし今後、ECサイトの仕様変更などでインターフェースに新たなメソッドを追加する必要があるときは、追加したいメソッドがどのドメインと関係するか吟味する。
その上で、既存のインターフェースに書き加えるべきか、それともインターフェースを新たに作成するか考える。

# ISPとSRPの関係
ISPは、インターフェースに関してSRPを適用した原則ととらえることができる。
すわなち、ひとつのインターフェースに対して、ひとつのドメインと関係するメソッドしか定義してはいけない。
[Python3] 正規表現で、括弧で括ったところの直後を数字に置換

**Python 3.7.3** で動作確認

```python
import re

url = "https://www.example.com/aaa/bbb/ccc?x=123&y=456&z=789"
re.sub(r"(?P<one>https://www\.example\.com/aaa/bbb/ccc\?x=123&y=)\d+(?P<two>&z=789)", r"\g<one>0\g<two>", url)
# "https://www.example.com/aaa/bbb/ccc?x=123&y=0&z=789"
```

`https://www.example.com/aaa/bbb/ccc?x=123&y=456&z=789`
のような文字列の`456`を`0`に変えて、
`https://www.example.com/aaa/bbb/ccc?x=123&y=0&z=789`
のようにしたくなりました。

いつもの調子で置換後を`r"\10\2"`と書いたところ、「`\1`と`0`と`\2`」ではなく「`\10`と`\2`」と解釈されたのかエラーが出てしまいました。そこで解決策を探すと、

>`(?P<name>...)`
>通常の丸括弧に似ていますが、このグループがマッチした部分文字列はシンボリックグループ名 name でアクセスできます。
>(中略)
>参照する方法： `\g<quote>`

>[ドキュメント日本語訳](https://docs.python.org/ja/3/library/re.html#index-17)より引用

という書き方がありました。
[メモ] StackView(コード)

StackViewをコードで書きたくなったとき用のメモ

## 全文
```swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        createStackView()      
    }

    func createStackView() {

        let imageView = UIImageView()
        imageView.backgroundColor = .systemGreen
        imageView.image = UIImage(systemName: "bell")
        imageView.contentMode = .scaleAspectFit
                
        let label = UILabel()
        label.backgroundColor = .systemBlue
        label.text = "Hello World"
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 21, weight: .bold)
        
        let label2 = UILabel()
        label2.backgroundColor = .systemOrange
        label2.text = "Another Label"
        label2.textAlignment = .center
        label2.font = .systemFont(ofSize: 21, weight: .bold)
        
        let stackView = UIStackView(arrangedSubviews: [imageView, label, label2])
        stackView.frame = view.bounds
        stackView.backgroundColor = .systemYellow
        // config
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        stackView.spacing = 20
        
        view.addSubview(stackView)    
    }
}
```
ソートアリゴリズム

# 要件定義 
- 数字をソートアルゴリズムを使ってソートする(Swiftのソート関数は使わない)
- 日本語ひらがな、アルファベット小文字の1文字をソートする
- インプットは数字の場合と、文字の場合がある
(ただし、文字と数字の組み合わせはない、どちらか1種類のみの羅列が入力される)
- 最後に昇順 or 降順の指定がある
- ユーザーは決まった手順を守るとは限らないので、その場合の例外の対応方法の組み込み
(無理矢理処理しても、エラーを返してもいい)

# システム設計
- 文字列を「数字」か「文字」で区別する
- 「文字」の場合Unicode文字に変換を行う
- バブルソートを行う
- 文字列の場合はソート後再び文字列に変換を行う
- 昇順の場合はそのまま出力し、降順の場合は逆順出力を行う

## 参考記事
▽【Swift 5】文字列を数値として処理（map）し、また文字列に戻す方法
https://www.ohitori.fun/entry/how-to-map-string-as-int
Laravelコマンドまとめ

Laravel初学者です。

各コマンドをいつも忘れてしまうのでメモです。


## Laravelバージョン確認

```PHP
php artisan --version
```

## モデル作成

```PHP
php artisan make:model Sample
```

下記のように`-m`をつけるとマイグレーションファイルも作成されます。

```PHP
php artisan make:model Sample -m
```


## コントローラー作成

```PHP
php artisan make:controller SampleController
```

下記のように`--resource`をつけると`index,show,create,store,edit,update,destroy`のアクションが用意されたコントローラーが作成できます。

```PHP
php artisan make:controller SampleController --resource
```

## マイグレーション

マイグレーション実行

```PHP
php artisan migrate
```

ロールバック(一番最後に実行したマイグレーションファイルだけ)

```PHP
php artisan migrate:rollback
```

全てロールバック

```PHP
php artisan migrate:reset
```

マイグレーションの状態を確認

```PHP
php artisan migrate:status
```


## ルーティング確認

```PHP
php artisan route:list
```

順次追記していきます。
UART を使ってマイコンボード - PC (Go のプログラム) 間で通信する

## ゴール

* UART がどんなものか何となくわかるようになる
* UART を使ってマイコンと PC で送受信ができるようになる
* UART を Go で使用して Windows から扱えるようになる

## 背景

マイコンボードで遊ぶにあたって、センサなど周辺モジュールは SPI や I2C のインターフェースとなっている事が多いです。 
なので、今まで UART は知っていても使ったことがありませんでした。 
今回は簡単な試作品を作成して、UART をマイコンで扱えるようにしてみようと思います。 

## UART とは

UART は、自分の認識では一般的に Serial 通信を行うための I/F としてよく用いられると思っています。 
Wikipedia による概要は以下です。 

UART (Universal Asynchronous Receiver/Transmitter, ユーアート) は、 
調歩同期方式によるシリアル信号をパラレル信号に変換したり、その逆方向の変換を行うための集積回路である。 
本機能のみがパッケージングされたICで供給されるものと、マイクロプロセッサのペリフェラルの一部として内蔵されるものとがある。 
マキシムのMAX232のような、RS-232C規格に準拠する信号レベルに変換するICと組み合わせて、外部機器とのインタフェースとして利用されるのが一般的である。 
[UART - Wikipedia](https://ja.wikipedia.org/wiki/UART)

## 今回やりたいこと

マイコンボードから送信した UART で送信したデータを、PC で受信して表示する。 

実際に動かすと、以下のように受信したデータをターミナルへ表示することができました。 

```
$ go build && uart_test.exe
[252]
[253]
[254]
[255]
[0]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
[11]
・
・
・
```

## ハードウェアのセットアップ

今回は以下のハードウェアを使用します。 

* Arduino Nano
    * https://www.switch-science.com/catalog/2554/
    * Arduino Nano 互換のマイコンであればなんでもよい
    * というか Arduino である必要もない
* USB - Serial 変換 IC の入った USB ケーブル
    * https://akizukidenshi.com/catalog/g/gM-05840/
    * FT232R の入った変換モジュールであればなんでもよい

以下のように配線をします。 
Arduino と変換モジュールのロジックレベルが異なるので、ロジックレベル変換モジュールを挟んでいます。

![uart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143910/c37ab05d-0923-1606-c5a7-7ea9b3a0e950.png)

## ソフトウェアのセットアップ

以下のようにそれぞれ送信側(マイコンボード)と受信側のソースコード(PC)を作成します。

### 送信側

```cpp
#include <SoftwareSerial.h>

SoftwareSerial mySerial(0, 1);

byte sendData = 0;

// the setup function runs once when you press reset or power the board
void setup() {
  mySerial.begin(115200);
}

// the loop function runs over and over again forever
void loop() {
  mySerial.write(sendData);
  sendData++;
  delay(100);
}
```

* 公式にある [SoftwareSerial ライブラリ](http://www.musashinodenpa.com/arduino/ref/)を使用
* 100ms ごとに送信データをインクリメントしながら送信する

### 受信側

```go
package main

import (
	"fmt"
	"log"

	"github.com/tarm/serial"
)

func main() {
	c := &serial.Config{Name: "COM4", Baud: 115200, Parity: serial.ParityNone, StopBits: serial.Stop1}
	s, err := serial.OpenPort(c)
	if err != nil {
		log.Fatal(err)
	}

	buf := make([]byte, 32)
	for {
		n, err := s.Read(buf)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(buf[:n])
	}
}
```

* サードパーティのライブラリ [tarm/serial](https://github.com/tarm/serial) を使用
* ブロッキング処理にて受信したデータを読み出して表示する

## 実際に動かしてみて気が付いたこと

* 通信速度が低い (9600bps とか) と、データが一定割合化けることがあった
  * 115200bps に設定したら、化けることはなくなった
  * どこかのセッティングが悪いと考えられるが、今回はわからなかった
* マイコンボードから速めの速度 (10ms 以下) で送信をすると受信側でデータを取りこぼす
  * これもどこのレイヤで発生しているか追及していないので、今回はわからなかった

## まとめ

* ハードウェアは手元にあるようなもので揃うことが多いので、試すハードルが低い
* USB Serial 変換ケーブルがあると、簡単に PC とも通信ができて、試すハードルが低い
* ソフトウェアのライブラリも、一般的な Serial 通信用のライブラリが使用できるので、試すハードルが低い
    * Windows 側の Go のライブラリも、シリアルポートが COM ポートで指定出来て楽だった
* 他のマイコンボードで使用するシリアル通信と比べると、データが化けたり取りこぼしたりするケースが多いと感じた
    * そのあたりはもう少し知識を掘り下げる必要がありそう
Azure FunctionsのログをApplication Insightsで確認する方法

# 概要
Azure Functionsで、プログラム中で仕込んだログを参照するのに手こずってしまったので、自分のメモがてら共有します。
Azure Portalからは、直近20件の実行分までは簡単に参照できるのですが、それより古い分はApplication Insightsを利用する必要があったのです。KQLとか、書き方がわからず困惑しました:confounded:

# ログを仕込む方法
(私はJavaでAzure Functionsを書く事が多いので、Javaの例のみとさせてください)
Functionsの入り口となるメソッドでは、`ExecutionContext`というクラスの引数を受け取れるようになっているので、ここからLoggerを取得する事ができます。
↓メソッド引数で`ExecutionContext`を受け取る

```java
    @FunctionName("HttpTrigger-Java")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, SystemException {         
```

`context.getLogger()`で`java.util.logging.Logger`が取得できるので、これを使ってログを出力する事ができます。

```java
context.getLogger().info("Java HTTP trigger processed a request.");
```

# 直近20件の実行分は「モニター」から参照できる
Azure Portalの「モニター」機能では、直近20件までの実行結果を簡単に確認する事ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230422/75db5404-b11e-20f2-4d4a-16cf6840aaae.png)

ここから、「日付」欄のリンクをクリックすると、仕込んだログを見る事ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230422/c183beaf-a73c-00bb-77b8-a3847a91f94c.png)

この20件より古い実行結果についてログを見るには、Application Insghtsを使用する事になります。

# Application Insightsでログを見るには
Application Insightでは、「KQL」というクエリ言語で様々な情報を参照する事ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230422/f60bad2b-92c0-2911-19ec-2ece96d7d94e.png)

例えば、下記のクエリで、直近3日で異常終了したアプリの情報を見る事ができます。
(この例だと、Azure Functions以外のアプリケーションについても出てきてしまうと思うので、その場合は`appName`の条件で絞る等試してみてください)

```
requests
| where success == false
| where timestamp > ago(3d)
| order by timestamp desc
| project timestamp,operation_Id,success
```

詳しい解説はしませんが、SQLが書ける人なら、だいたいどんな事がしたいかわかると思います。
Ctrl + spaceで、項目や条件を追加できるので、ログを参照したい実行結果を探してみてください。
(`where`の所には条件を、`project`の所には参照項目を追加する感じです。)

特定できたら、KQLの結果から`operation_Id`をコピーして、今度は下記のようなKQLを実行します。
`operation_Id ==`の所に、コピーした`operation_Id`を貼り付けてください。

```
union traces
| union exceptions
| union requests
| where timestamp > ago(3d)
| where operation_Id == '17d736d3896baa4a893e2c3f46103a52'
| order by timestamp asc
| project timestamp, message = iff(message != '', message, iff(innermostMessage != '', innermostMessage, customDimensions.['prop__{OriginalFormat}'])), logLevel = customDimensions.['LogLevel']
```

無事、「モニター」で見るのと同じログを見る事ができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230422/14cb2989-95cc-c71a-e713-030ed38cfb6b.png)


慣れてきたら、下記のKQLでも良いと思います。
複数回の実行結果分をまとめて見る事もできます。

```
requests
| where success == false
| where timestamp > ago(3d)
| join kind=inner (
traces 
|where timestamp > ago(5d)
) on operation_Id
| union exceptions
| order by timestamp desc
| project timestamp, message = iff(message != '', message, iff(innermostMessage != '', innermostMessage, customDimensions.['prop__{OriginalFormat}'])), logLevel = customDimensions.['LogLevel'],success,operation_Id
```
Vue 3 の Composition API における watch vs watchEffect

## はじめに
Composition API を使用する上で、`watch` と `watchEffect` って何の違いがあって、どういう時にどっちを使えばいいのか、わからない...
Vue3 の公式ドキュメントには、`watchEffect` と比べて `watch` には以下のメリットがある、と書かれています。あまりにサラッと書かれていて、腹落ちしなかったので、これらを整理した結果をメモとして残します。

> https://v3.ja.vuejs.org/guide/reactivity-computed-watchers.html#watch
> 1. 作用の効率的な実行
> 1. ウォッチャの再実行条件の明文化
> 1. ウォッチされている状態に対しての、変更前後の値両方へのアクセス


## 結論
大きな違いは監視対象の定義の仕方なので（あくまでも個人的な結論）、どちらでも好きな方を使えばいいと思います。`watch` と `watchEffect` は、使い方に違いはありますが、実際のユースケースを考えたとき、どちらの方が何に向いている、という決定的な違いはないかな、と思ったので、こういう結論です。（`watch` と `watchEffect` の使い分けに関するコメントがあれば頂きたい...）

ただ、`watchEffect` の方がシンプルに定義できるので、様々な場面でスッキリとコードを書けるのは `watchEffect` の方だと思います。少なくとも Composition API を使う人は、`watchEffect` を使う方が多いと思います。


## watch と watchEffect の違い

公式ドキュメントとは、若干異なりますが（重複もあります）、個人的に見た中でここが違うな、と思った部分を3つピックアップしています。

- 監視対象の定義の仕方
- watch は変更前と変更後の値が取得できる
- 初回実行のタイミング


## 監視対象の定義の仕方

`watch` は、監視対象のオブジェクトを第 1 引数に指定します。
`watchEffect` は、関数の中で使用されているリアクティブオブジェクト(※)が監視対象になります。
※ リアクティブオブジェクトとは、`reactive()` や `ref()` により定義されたオブジェクトのことを指しています。

```javascript
const { ref, watchEffect, watch } = require('vue')

const price = ref(100)
const count = ref(1)
let watchResult = 0
let watchEffectResult = 0

// 監視対象は price であり count は監視対象外
watch(price, () => {
  watchResult = price.value * count.value
})

// 監視対象は price と count
watchEffect(() => {
  watchEffectResult = price.value * count.value
})
```

`watch` は、明示的に監視対象を指定しているのに対し、`watchEffect` は明示的には監視対象を指定しません。

ここからは個人的な意見です。
この違いが `watch` と `watchEffect` の中で、一番大きいと思います。( 念の為に... `watch` では複数のオブジェクトを監視できない、というわけではないです。第 1 引数に配列で渡せば複数のオブジェクトを監視対象にできます。)

`watch` は、明示的に監視対象を指定している分、Vue の初心者にとっては扱いやすいのではないかと思います（半年前の自分だったら `watch` を使います...）。
一方、 `watchEffect` の方が定義の仕方はシンプルです。ある程度 Composition API のリアクティブシステムに親しみがある方にとっては、`watchEffect` の方がシンプルで良いね、となるのではないでしょうか。


## watch の変更前と変更後の値が取得できる

`watch` は、変更前と変更後の値が引数として渡されます。
`watchEffect` は、渡されないです。

```javascript
watch(price, (newValue, oldValue) => {
  console.log({ newValue })
  console.log({ oldValue })
})
```
`watchEffect` で同じことをやろうと思ったら、自分で変更前と変更後の値を定義する必要があります。個人的には、定義すればいいんじゃない？と思うので、差ではありますが、あまり気にしなくていいかなと思います。


## 初回実行のタイミング

`watch` は、定義時には実行されません。
`watchEffect` は、定義時に実行されます。
`watch` と `watchEffect` を定義した直後に、それぞれの関数の結果を `console.log` で表示しています。

```javascript
const { ref, watchEffect, watch } = require('vue')

const price = ref(100)
const count = ref(1)
let watchResult = 0
let watchEffectResult = 0

watch(price, () => {
  watchResult = price.value * count.value
})

watchEffect(() => {
  watchEffectResult = price.value * count.value
})

console.log({ watchResult })
// 0 で定義し、値は更新されず、0 のまま
// { watchResult: 0 }

console.log({ watchEffectResult })
// 0 で定義したが、値は更新され、100 になっている
// { watchEffectResult: 100 }
```

`watch` の初回実行のタイミングは、監視対象のオブジェクトが変更されたタイミングです。
上記の例の場合だと、`price` を変更したタイミングが `watch` の初回実行タイミングです。

ここからは個人的な意見です。
この違いは、覚えておこうレベルだと思います。Web の初期表示時などで覚えておかないとハマりそうかなー、という程度です。


## まとめ

結論は、冒頭に書いた通りです。自分は、`watchEffect` を使います。
【Rails6】AWS S3のバケットを複数のアプリに適用させる方法

#概要
AWS S3のバケットを複数のアプリに適用させる方法について述べています。

#前提
AWS S３を導入していることが前提の記事となっています。

S３は複数のアプリに共通のバケットを使用させても、無料枠内の使用容量であれば、無料で使用できます。

#背景
転職活動中の筆者が、転職先の企業さんに提出するためのアプリを2つ作成し
共通のバケットを2つのアプリに適用させた、その一連の流れを紹介しております。

#この記事がおすすめの方
AWS S３を導入後、複数のアプリに共通のバケットを適用させたい方向けの記事となっています。

#バージョン
rubyのバージョン　ruby-2.6.5
Railsのバージョン Rails:6.0.0

#実装の全体像
①gem "aws-sdk-s3"をbundle install
②development.rbを編集
③storage.ymlにバケット名とリージョン名、環境変数を記述
④git-secretsを設定して、セキュリティー対策
⑤git-secretsの条件を設定
⑥production.rbを編集
⑦Heroku上でも環境変数を使えるよう設定
⑧masterブランチにマージ
⑨Herokuに反映

#実装の手順
##①gem "aws-sdk-s3"をbundle install
設定を適用したいアプリケーションのディレクトリに移動します。

```
cd アプリケーション名 #開発中のアプリに移動
```

S3を実装したいアプリのGemfileの一番下に以下を追記します。

```Gemfile
gem "aws-sdk-s3", require: false
```

追記したらターミナルでbundle installを実行します。

```
$ bundle install
```

##②development.rbを編集
現状では画像の保存先が「local」に設定されているので、S3に保存されるように設定を変更します。

（変更前）

```config/environments/development.rb

# ~省略~

config.active_storage.service = :local

# ~省略~

```
↓

（変更後）

```config/environments/development.rb

# ~省略~

config.active_storage.service = :amazon

# ~省略~

```

##③storage.ymlにバケット名とリージョン名、環境変数を記述
S3で使用するバケット名とリージョン名、環境変数を記述します。

```config/storage.yml
test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

amazon:
  service: S3
  region: ap-northeast-1
  bucket:  （自身のバケット名が記載されている状態です）
  access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
  secret_access_key:  <%= ENV['AWS_SECRET_ACCESS_KEY'] %>

# ~省略~

```

※別アプリで、一度S3で環境変数をセットしている場合は、自動的に環境変数にアクセスキーが代入されています。
　もしセットされてない方は vim ~/.zshrcでの編集作業を行い、環境変数にアクセスキーを代入してください。

##④git-secretsを設定して、セキュリティー対策
git-secretsをインストールします。

```
$ git secrets --install
```

##⑤git-secretsの条件を設定
「Access key ID」「Secret access key」など、アップロードしたくないAWS関連の秘密情報を一括で設定します。

```
$ git secrets --register-aws --global
```

##⑥production.rbを編集
ローカル環境での設定と同様に、画像の保存先を指定します。
現状では画像の保存先がローカルに設定されているため、S3に保存されるように設定を変更します。

（変更前）

```config/environments/production.rb

# ~省略~

config.active_storage.service = :local

# ~省略~

```
↓

（変更後）

```config/environments/development.rb

# ~省略~

config.active_storage.service = :amazon

# ~省略~
```

##⑦Heroku上でも環境変数を使えるよう設定
それぞれの右辺に「Access key ID」「Secret access key」の値をコピーして貼り付けます。

```
$ heroku config:set AWS_ACCESS_KEY_ID="CSVファイルのAccess key IDの値を貼り付け"
```

```
$ heroku config:set AWS_SECRET_ACCESS_KEY="CSVファイルのSecret access keyの値を貼り付け"
```

設定されているかの確認はheoku configでできます。

```
$ heroku config
```

##⑧masterブランチにマージ
GitHubでコードの変更内容をマージしてください。

##⑨Herokuに反映

```
$ git push heroku master
```

##⑩確認
S3のバケットにファイルが保存されているか確認します。
まず、以下の手順でバケットのページに遷移しましょう。

AWSのサイト画面上部のメニューバーから「サービス」をクリック
サービス一覧から「S3」を選択
「バケット名」をクリック

以下の手順で投稿した画像が保存されているか確かめます。

①一度リロードして情報を最新の状態にする
②バケットの詳細ページで画面を下にスクロールする
③「オブジェクト」という項目の中に投稿した画像があるか確認する
【確認方法①】 最終更新日時が投稿した時間と一致しているか
【確認方法②】 オブジェクトをクリックし詳細ページを開く。「オブジェクトアクション」から「開く」をクリックし、同じ画像が表示されるかどうか

確認でき、画像がHeroku上で反映されていれば以上となります。

#補足説明
##git-secrets
AWSが公開しているツール
commitしようとしたコードをチェックし、パスワードだと推定されるような文字列が含まれている場合は、警告を出して処理を中断してくれる機能です。
【React】テキストエリアコンポーネントから親コンポーネントにフォームの内容を渡す

子コンポーネントから親コンポーネントに対して値を渡す記事そのものは多少あるのですが、テキストエリア内の値の受け渡し方法というのは、あんまり見受けられなかったため個人用の備忘録です。

```react:parent.tsx(Signup.tsx)

const Signup: React.FC = () => {
  const [email, setEmail] = useState("");

  return (
    <div>
      <Textbox
        placeholder="email"
        onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
          setEmail(event.target.value)
        }
      />

      {email}
    </div>
  );
};
```

parent.tsx内ではTextboxコンポーネントにonChange関数を渡しています。帰ってきた値をReactHooksのstateに値を格納しています。

```react:children.tsx(Textbox.tsx)

interface Props {
  placeholder: string;
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

const Textbox: React.FC<Props> = ({ placeholder, onChange }) => {

  return (
    <input
      type="text"
      placeholder={placeholder}
      onChange={onChange}
    />
  );
};
```

ここではPropsにonChange関数の型の定義をした後、テキストエリア内で変更があったらそのまま親コンポーネントのonChange関数を発火させるようになっています。
chrome dns キャッシュを削除しよう

nginx を設定しました。
ドメインを設定しました。

新しいドメインをテスト。
あれ？古いドメインにリダイレクトされちゃうよ？

そんなときの対応方法
ブラウザに以下のURLを入力しましょう。

まずはこれでDNSを削除できます

```
chrome://net-internals/#dns
```

表示されたボタンをクリック。


これでもうまく行かない場合は以下のコマンドで


```
chrome://net-internals/#hsts
```

ドメインを入力し、Addを押せば新しいドメインが表示されるようになります。
UITextFieldでキーボードのサジェストとフォーカスの動きが意図しない件について

# 事の始まり
サービスの新規登録画面を作り直すことになりました。

内容としては簡単なもので、項目は以下の通り。
・メールアドレス入力
・パスワード入力
・パスワード再入力

`UITextField`をパラパラっと設置して、キーボードのタイプを指定して、

最後にパスワードは見えないように`isSecureTextEntry`を忘れずに。

簡単ですね😀！！

```SignUpViewController.swift
class SignUpViewController: UIViewController {
    @IBOutlet private weak var emailAddressText: UITextField!
    @IBOutlet private weak var passwordText: UITextField!
    @IBOutlet private weak var rePasswordText: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        emailAddressText.keyboardType = .emailAddress
        emailAddressText.isSecureTextEntry = false
        emailAddressText.textContentType = .emailAddress

        passwordText.keyboardType = .asciiCapable
        passwordText.isSecureTextEntry = true
        passwordText.textContentType = .password

        rePasswordText.keyboardType = .asciiCapable
        rePasswordText.isSecureTextEntry = true
        rePasswordText.textContentType = .password
    }
}
````

# 動かしてみる＆問題が見つかる
まずメールアドレス入力、次にパスワード入力、最後にパスワード再入力っと。

ん？？？

なんでパスワード再入力時に`メールアドレス`、`ユーザ名`のサジェストが出てくるんだ・・・🤔

しかもサジェストを選択すると`メールアドレス`に入力されてフォーカスがパスワード入力に移動する😇

# 調査してみる
きっと`textContentType`が間違っているんだ！

と、いうことで色々組み合わせを変えてみる。

### まずは何も指定しないケース

||emailAddress|password|rePassword|
---|---|---|----
|isSecureTextEntry|false|false|false|
|textContentType|nil|nil|nil|

これは問題なし。サジェストは表示されず、想定通りの動き。

しかしパスワード丸見えなのでサービスとしては駄目。

### 次に色々と指定してみるケース

||emailAddress|password|rePassword|
---|---|---|----
|isSecureTextEntry|false|true|true|
|textContentType|username|password|password|

||emailAddress|password|rePassword|
---|---|---|----
|isSecureTextEntry|false|true|true|
|textContentType|nil|nil|nil|

||emailAddress|password|rePassword|
---|---|---|----
|isSecureTextEntry|false|false|false
|textContentType|username|password|password|

||emailAddress|password|rePassword|
---|---|---|----
|isSecureTextEntry|false|false|false
|textContentType|username|newpassword|newpassword|

||emailAddress|password|rePassword|
---|---|---|----
|isSecureTextEntry|false|false|false
|textContentType|username|password|password|

組み合わせとしては全部駄目でした。

サジェストが出てしまいフォーカスも意図しない動きになる。

どうやら`isSecureTextEntry`、`textContentType`をいじるとサジェストが出てしまうようだ・・・🤔

パラメータの組み合わせで解決するかなと思ったが駄目みたい。

# 教えてApple!!
というわけでApple Technical Support Incidentを投げてみました。

https://developer.apple.com/jp/support/technical/

やりとりの内容としては以下の通りです。

筆者「UITextFieldを3つ置いてtextContentTypeとisSecureTextEntryを指定します。」

筆者「特定の組み合わせで意図しないサジェストが出てしまいます。解決方法はないでしょうか？」

Apple「問題を解決するため問題箇所に特化したサンプルプロジェクトを送って下さい。」

〜サンプルプロジェクトを送る〜

Apple「フィールドのキーボードの提案、またはプロジェクトが示す動作は、システムのバグと見なされます。（Google翻訳）」

Apple「Feedback Assistantでバグレポートを送って下さい。」

とのことでした。

# おわりに

とりあえずバグレポートは作成して報告したので修正を待とうと思います。

今回初めてTSI投げましたが、解答が早く不具合もすぐ認めてくれたので正直びっくりしました。

以上です。
dynabookにLinuxをインストールする

Linuxを学習するにあたり、実機(PCもしくは仮想マシン)を用意して実際に操作してみることが最も効率良い方法だと思ったため、今回はPCを用意してLinuxをインストールしてみることにしました。

#Linuxディストリビューションについて
Linuxをインストールするにあたって調べていたところ様々なディストリビューションが存在していることが分かりました。
今回は人気があると言われているUbuntuをインストールすることにしました。

ここで「元祖Linuxはどれなのか」という疑問が生じたので調べてみたところ下記のURLにたどり着きました。
https://www.kernel.org/
C言語とアセンブリ言語のコードでしょうか。全て読もうとしたら日が暮れてしまいそうです。

#用意したもの
* TOSHIBA dynabook(中古ノートPC)
 
|CPU |RAM |ストレージ容量 |OS |
|:-: |:-: |:-: |:-: |
|intel corei7-3630QM |8GB |1TB |Windows10 HOME 64ビット |

* USBメモリー(16GB)

#手順
1. USBメモリーにUbuntuのISOをインストールする
2. dynabookにUSBメモリーを挿入してBIOSを立ち上げる
3. BIOSの起動メニューからUSBメモリーを選択してインストールする

上記の手順で行うことにします。

#1. USBメモリーにUbuntuのISOをインストールする
* [Ubuntu Japanese TeamのHP](https://www.ubuntulinux.jp/)からUbuntuのISOイメージをダウンロードする。
* USBメモリーから起動したいたので[Rufus](https://rufus.ie/ja_JP.html)をインストールします。
* Rufusを使って先ほどダウンロードしたUbuntuISOイメージを書き込む。  
<br>
これでブート可能なUSBメモリーができました。

#2. dynabookにUSBメモリーを挿入してBIOSを立ち上げる

* dynabookに先ほど作成したUSBメモリーを挿入しBIOSを立ち上げます。  
(dynabookは起動後にF2を数回押すと立ち上がる)  
<br>
ここで問題が発生。BIOSがUSBメモリーを認識しません。  
いろいろ調べたところUSBを差し込む場所が原因のようで左側に一つだけあるUSBポートに差したところ認識しました。

#3. BIOSの起動メニューからUSBメモリーを選択してインストールする

* 起動メニューからUSBを選択して立ち上げる  

![IMG_9302.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964196/3a3d330c-ce1c-8f8f-dc0d-1f4b87cba5ae.jpeg)

ここで問題が発生。
USBから起動してもうまく立ち上がりません。  
調べてみたところセキュアブートが「使用する」になっているとうまく立ち上がらないことが判明しました。

![IMG_8996.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964196/d7e20949-bf4f-1acc-d58e-82bc3e86ee6f.jpeg)

セキュアブートを「使用しない」にします。

![IMG_8988.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964196/b258df37-5c71-107b-c8c4-7dc0dcccfa86.jpeg)

立ち上がりました。

![IMG_8990.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964196/a1f21b5d-e3dc-f427-a3d4-597f290a0c22.jpeg)

ここでWindowsを完全に削除します。
このPCはWindowsとして使用することができなくなります。

![IMG_8991.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964196/b7255e24-c844-60a9-be3f-f3c5060ef7e2.jpeg)

インストールが完了しました。
URLをパースするJavascript



#URLのパースとは

URLの文字列を役割ごとに分解することです。例えば、
https://example.com/dir1/dir2/index.php?aaa=111/bbb&bbb=7#hello
というURLがあったとします。

前から順に、

| 部分 | 名称| 説明 |
|:-:|:-:|:-:|
| https:// | プロトコル (スキームと呼ぶこともある)  | この例は Web上のリソースへ「SSLでアクセスする」ことを表しています。|
| example.com  | ホスト名、サーバー名  | アクセス先のサーバーを指定しています|
| dir1/dir2/index.php  | パス（path、英語の「道、経路」）  |サーバーの中の、どのファイル（またはプログラム）にアクセスするか、その位置とファイル名を表しています。 |
| aaa=111/bbb&bbb=7  |  クエリー | プログラムに渡す情報（パラメーター）が、「?」の後に続きます。複数のパラメーターは「&」で区切ります。|
| hello   | ハッシュ  |ブラウザで表示処理する際の目印。ページ内リンクなどで利用されます。「#」の後に続きます。 |


もちろん、基本的にはすべて半角英数字です。



#JavascriptでURLを分解するスクリプト
```javascript:

//元のURL
var url ="https://example.com/dir1/dir2/index.php?aaa=111/bbb&bbb=7#hello";

//分割して変数に格納します。
var protocol= url.split(':')[0];
var hash   = url.split('#')[1];
var query  = url.split('#')[0].split('?')[1];
var host   = url.split('#')[0].split('?')[0].split('/')[2];
var path   = url.split('#')[0].split('?')[0].replace(host,"").replace(/^https*:[\/]{3}/,"");

//ブラウザのコンソールに出力します
console.log( protocol ); // https
console.log( host ); // example.com
console.log( path ); // dir1/dir2/index.php
console.log( query ); // aaa=111/bbb&bbb=7
console.log( hash ); // hello
```

以上です。
PHPでは、parse_url という便利な関数がありますが、
それと似たような動きとなります。
【Express】Hello Worldを出力する

#プログラミング勉強日記
2021年2月22日
[一昨日の記事](https://qiita.com/mzmz__02/items/03c4bb839a5e5abe02a8)でNode.jsの3大フレームワークについて取り上げた。今日は、ExpressでHello Worldを表示する方法をまとめる。

#Expressを導入する方法
　<b>Node.jsの開発環境が構築されていることを条件とする。</b>Node.jsの環境構築がまだの人は[こちらの記事(Windows版)](https://qiita.com/mzmz__02/items/6cc53f06205fd11367bc)を参考に環境構築してみてください。
　npmを使ってExpressをインストールするだけで、Expressを導入することができる。

```
$ npm install express
```

#Hello Worldを出力する
　JavaScriptファイルを作成する。今回は`app.js`という名前のファイルを作成した。ポート番号を8080に設定してるので、今回は`http://localhost:8080/`にアクセスするとHello Worldが表示できる。

```js:app.js
// ExpressをNode.jsから使えるようにする
const express = require('express');
const app = express();

// ホストディレクトリ(/)でHello Worldを出力する
app.get('/', function (req, res) {
    res.send("Hello World");
});

// サーバーを起動する
app.listen(8080);
```

```:ターミナル
$ node app.js
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/273874f6-5349-0788-6e14-2bfd99220c55.png)
アジャイルサムライ　達人開発者への道　まとめ

アジャイルサムライを読んで自分なりにまとめてみます。


## イテレーションの運営
p187

ストーリーを実際に動くソフトウェアとして実現させるために以下の３ステップがある。

- 分析して設計する（作業を段取りする）
- 開発する（実際に作業する）
- テストする（作業の結果を確認する）

## 分析して設計する
「必要な分だけ、必要なときに、　分析する」

**必要な分だけ**
→チームにとって適切なレベルで分析されているのかどうかが大事

**必要なときに**

→ユーザーストーリーを実装するタイミングが近づいてから、突っ込んで分析する
　　→具体的には、ストーリーを実装を予定しているイテレーションの１つ前のイテレーションで分析する

**メリット**

- 最新かつもっとおじゅじつした情報に基づいて分析できる
- 手戻りが大量発生しない


##### 分析対象が複雑で時間がかかりそうなとき有効な手段
- フローチャート
- ペルソナ
- 受入テスト
###### フローチャート
（写真）
システムの動作や必要な手順をシンプルに示してくれる

###### ペルソナ
（写真）
ソフトウェアのユーザーを役割ごとに簡単に説明したり、典型的な姿として描くもの

##### 受入テスト
どのように機能したらうまく動いているのかを詳細を書く
お客さんに聞きながら作業するべき機能をしっかりと把握する。

## 開発する
先ほど分析したことを現実のものに実現していく。


12,13,14,15章で解説されるらしい

## テスト

いつでも受入テストできるようにすること。
お客さんがどのように使うのかを見ながら行うと尚良し。
Animate CC preloading error

Animate CC で HTML5 に書き出した後、ブラウザの読み込み時に次のエラーが出ることがあります

Uncaught TypeError: Cannot read property 'getContext' of undefined

出る時と出ない時があるので厄介かつ、このアラートでは見当もつかずに試行錯誤をした記憶があるのですが、以下のサイトで理由と解決方法がわかりました。

[Preloading error with canvas project on first load with a large spritesheet file](https://community.adobe.com/t5/animate/preloading-error-with-canvas-project-on-first-load-with-a-large-spritesheet-file/td-p/10782224?page=1&profile.language=en)

>
If one or more of your assets is taking longer than 8 seconds to load, that's probably what's causing the page to fail. Also your page is loading too much and is going to be a bad user experience.
 
There appears to be no official way to specify a longer timeout, so to extend the timeout period you'll have to manually hack up your generated code. The simplest way appears to be to increase the default timeout. In the libs/createjs file, search for LOAD_TIMEOUT_DEFAULT=8e3. The "8e3" is 8000 written using engineering notation. The 8000 is milliseconds, or 8 seconds. Change the 3 to 4. This gives you an 80-second timeout per asset. The createjs file is overwritten every time you publish, so keep a backup copy of the modified version.


createjsのデフォルトロードウェイト時間が８秒なのが原因でした。
なのでブラウザで読み込みが8秒以上かかるとエラーになります。

解決方法はHTMLで読み込まれているcreatejs.min.jsのLOAD_TIMEOUT_DEFAULTを8e3(=８秒)から変更します

8e4にすると８０秒ロードウェイトします。
【SwiftUI】パスワード 表示 非表示 目玉

# これはなに

パスワード入力フォームにおいて目玉アイコンをクリックすると表示と非表示を切り替えられる実装と解説。

## 実装と解説

```swift
// パスワードの初期値
@State var password = ""

// メンバ変数でフラグを持たせる。trueならば非表示
@State var passHidden = true

// 中略

// textFieldと目玉アイコンを重ねて表示
ZStack {
    // textFieldと目玉アイコンを横に並べて表示
    HStack {
        if self.passHidden {
            // 非表示
            SecureField("入力してください", text: self.$password)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .frame(width: 320, height: 40, alignment: .center)
                // 重ねて表示するための位置調整
                .offset(x: 15, y:0)
            
        } else {
            // 表示
            TextField("入力してください", text: self.$password)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .frame(width: 320, height: 40, alignment: .center)
                // 重ねて表示するための位置調整
                .offset(x: 15, y:0)
        }
        Button(action: {self.passHidden.toggle() }) {
            // アイコンそれぞれの名前を指定
            Image(systemName: self.passHidden ? "eye.slash.fill": "eye.fill")
                // アイコンそれぞれの色を指定
                .foregroundColor((self.passHidden == true) ? Color.secondary : Color.gray)
        // 重ねて表示するための位置調整
        }.offset(x: -32, y:0)
    }
}
```

おわりです。
textFieldの大きさなどは適当にどうぞ。
ソフトウェアのテスト技法

#　はじめて学ぶ　ソフトウェアのテスト技法　を読んだまとめ

この記事は2021年2月22日から毎日一項目追記していく予定です。

- 同値クラステスト
- 境界値テスト
- デシジョンテーブルテスト
- ペア構成テスト
- 状態遷移テスト
- ドメイン分析テスト
- ユースケーステスト
- 制御フローテスト
- データフローテスト
- スクリプトテスト
- 探索的テスト
- テストの計画

## 同値クラステスト
同値クラステストは、十分なテストカバレッジ（＝テストによってカバーできる範囲）を保ちながら、テストケースの数を管理可能な程度に減らすための技法のひとつ。

###具体例
**人材を年齢で雇用形態を判別するシステム**を作っているとします。

| 年齢 | 雇用形態 |
|:-:|:-:|
|  0歳~15歳 | 雇用せず  |
| 16歳~18歳  | パートとして雇用  |
| 19歳~55歳  | 正社員として雇用  |
|  56歳~99歳 |  雇用せず |

この場合、0~99歳まで1歳ずつテストをしていくのではなく、各年齢ブロック（0~15歳等）から
一つずつのサンプルを取り出してテストすることで、すべてのテストが完了することになる。

これにより、0~99歳までの**100回**のテストする必要がなく、たった**4回**のテストをすればよいことになるということである。

### 同値クラス　とは
モジュールで同等に処理されるデータあるいは同じ結果を返すデータの集合を意味する。

具体例の場合だと、0~15までは同値クラス、16~18までも同値クラス、18~55までも同値クラス、、のように続く。

→同値クラス内の、あるテストケースで欠陥が検出された場合、同じ同値クラスの他のすべてのテストケースで同じ欠陥が検出される。

具体例の場合だと、各同値クラスから一つのサンプルをテストするだけで網羅的にテストしたことになる。


## 境界値テスト
- 同値クラスの境界値に注目するテスト
- 同値クラスの境界値を発見し、そのすぐ前後の値をテストする
- 境界値テストが最も有効なのは、入力値が連続的な範囲を持つ場合
- 必要な条件は、システムの要件に基づいて入力がクラスに分割できることと、境界値が認識できること
- メリットは、十分なテストカバレッジを保ちながらテストケースの数を管理可能な程度に減らすことができること


## デシジョンテーブルテスト
-
Google DriveのAPIをNode.jsから触るメモ


Google Drive API v3を触ります。
google-auth-token-generatorを使ってtoken.jsonの作成をしてみる版です。

> 以前書いた記事も参考に: https://qiita.com/n0bisuke/items/ff1479cd14e7a0c0be0c

## 環境

* Node.js v15.9.0

## credentials.jsonを取得

チュートリアルを参考にAPIを有効にし、credentials.jsonを手元に保存しましょう。

> https://developers.google.com/drive/api/v3/quickstart/nodejs

## google-auth-token-generatorでtoken.jsonを作成

google-auth-token-generatorを使うとパーミッションをつけたtoken.jsonを作成しやすいです。

> 利用イメージ
> ![](https://camo.githubusercontent.com/91dc29cde99aa2b53b192532c6bfb40a5d8fba8cd464257d95ea9ed2a974f83d/68747470733a2f2f692e6779617a6f2e636f6d2f39326237336231323533353934613563333937363130373934393263623964612e676966)

`credentials.json`のあるディレクトリで、以下を実行します。

```bash
$ npx google-auth-token-generator
```




GoogleDriveを選択し、パーミッションを選択して進めましょう。

ファイルの一覧取得のパーミッションは`drive.metadata.readonly`になります。

```
https://www.googleapis.com/auth/drive.metadata.readonly
```

`token.json`が保存されます。

## app.jsを作成

`credentials.json`と`token.json`と同じディレクトリにapp.jsを作成する想定です。

```app.js
'use strict';

const fs = require('fs');
const {google} = require('googleapis');

const googleAuth = () => {
  const CREDENTIALS_PATH = 'credentials.json';
  const TOKEN_PATH = 'token.json';  
  const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
  const token = JSON.parse(fs.readFileSync(TOKEN_PATH, 'utf8'));

  const {client_secret, client_id, redirect_uris} = credentials.installed;
  const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
  oAuth2Client.setCredentials(token);
  
  return oAuth2Client;
};

(async () => {
  const auth = googleAuth();
  const drive = google.drive({version: 'v3', auth});

  try {
    const res = await drive.files.list({
      pageSize: 10,
      fields: 'nextPageToken, files(id, name)',
    });
  
    const files = res.data.files;
    if (files.length) {
      console.log('Files:');
      files.map((file) => console.log(`${file.name} (${file.id})`));
    } else {
      console.log('No files found.');
    }
  } catch (error) {
    console.log('The API returned an error: ' + error);
  }

})();
```

```
$ node app.js
```

## 参考記事

* https://qiita.com/n0bisuke/items/ff1479cd14e7a0c0be0c
R初心者のころに思った初歩的な疑問

Rを使い始めた頃の自分に捧げる。

#Rってなんなの？
自分がとったデータを入れればありとあらゆる統計処理ができるやつ。使うのにお金がかからない。統計処理以外にも、データそのもののクリーニングをしたり、図を描いたり地図を描いたり表を描いたり、だいたいなんでもできる。
すごい人たちが計算とか描画の枠組み（パッケージという）を作ってくれているのでそういうことが可能であるらしい。枠組みとデータがあればR上ではルール通りに計算がおこなわれるだけなので、新しいパッケージをインストールしさえすれば新しい機能が使えるようになる。

イメージ的には
R：倉庫と作業場
パッケージ：お道具箱
自分のデータ：材料
作りたいものに合わせて、お道具箱＝パッケージを選んで工作をする。工作したり製作途中のものや完成品を置いたりするための場所がR。

#データの中身が見えないし何が起こってるのかわからない、excelの世界に帰りたい
Rで大きいデータ処理を始めた頃に思っていた。慣れた頃にRは便利だなあと思ったのは、
・データ加工の手順が残る
・ボタンひとつで何度でも同じ処理ができる
・excelでできないデータ抽出ができる
・データクリーニング～統計処理～描画を同じ場所でできる
…excelでもマクロとかVBAを使えば履歴は記録できるし別のデータセットに同じ加工をすることもできるけど。

#関数？が覚えられない。
書いてみるしかない。がんばってほしい。