OmniAICreator/Qiita-1.07M huggingface dataset:
Page Object Model (POM)を使った自動テストについて3分で理解する

<H2>ページオブジェクトパターンをざっくり言うと？</H2>

ページオブジェクトパターン【Page Object Model (POM) とも言う】はテスト対象の画面テストをテスト自動化する際、画面というのは頻繁に変更が入り、自動テストも頻繁に修正が必要となる為、極力、自動テストをメンテナンスしやすいように作る、デザインパターン。

<h2>具体的には？</h2>

テスト対象の各画面情報を1画面につき、<font color="red">1つの共通クラスに集約し、</font>画面構成の変更に伴うスクリプト修正コストを減らすことができます。

* 全体イメージを図で書くと ↓
![POM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/58fa8704-e388-00bd-554a-ea0318a13919.jpeg)

* つまりは・・ ↓

![POM_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/8df7fc9d-c73c-9ad5-e1c4-ef0d4fe56f37.jpeg)




<h2>なぜメンテナンスしやすいのか？</h2>

* <STRONG>テストスクリプトが読みやすい</STRONG>
 * ローケータの詳細などをページオブジェクトのメソッド内に書くことでテストスクリプトを読みやすくする 
* <STRONG>1つのページに1つのクラスを作成する。というルールが明確</STRONG>
 * ルールが明確なので開発者ごとのバラつきがない
* <STRONG>メソッドが見つけやすい</STRONG>
 * 操作対象のページに対するページオブジェクトから目的のメソッドを探せばよいので、見つけやすい 
 * 操作対象のページのUI上の操作と簡単にマッピングしやすい(例：ボタンをクリックした後にホームページに移動するメソッドの場合、「gotoHomePage（）」にする、、とか）

<h2>サンプル</h2>

サンプルコードはググればいくらでもあるので、他サイトを参照
https://www.guru99.com/page-object-model-pom-page-factory-in-selenium-ultimate-guide.html

以上、3分で理解できたはず！？

<h2>参考記事</h2>
* [Page Object Model](https://docs.katalon.com/katalium-framework/docs/katalium-framework-page-object-model.html)
* [Page Object Model (POM) & Page Factory: Selenium WebDriver Tutorial](https://www.guru99.com/page-object-model-pom-page-factory-in-selenium-ultimate-guide.html)
* [Selenium実践入門 ―― 自動化による継続的なブラウザテスト](https://www.amazon.co.jp/Selenium%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E8%87%AA%E5%8B%95%E5%8C%96%E3%81%AB%E3%82%88%E3%82%8B%E7%B6%99%E7%B6%9A%E7%9A%84%E3%81%AA%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%83%86%E3%82%B9%E3%83%88-WEB-PRESS-plus/dp/4774178942)

余談。。。
> 3分で理解するシリーズ
> * [組合せテストの技法: ペアワイズ法(オールペア法)を3分で理解する](https://qiita.com/RyomaMaeda/items/27456cd5f01cdb8f4598)
> * [ TEST-HACK | 3分で理解するIT/テスト技術](https://test-hack.com/)
ネーミングセンスが悪い人へ

## はじめに
センスが無い私が感じた変数名、関数名を適切につける意義と
名付け方のチート技について書きたいと思います。

## ネーミングセンスをつける意義
「ネーミングセンス」
文字通り、変数名、関数名を決めるのにセンスが必要です。
じゃあセンスの悪いエンジニアはどうなるのかというと、周りの人に迷惑をかけます。
何のための関数、変数なのかをコードをひと目見ただけで判断できないからです。

そんなセンスがなく、コードのレビューが通らない私は、**省略するから分かりにくいのか！！！**
と悟りを開き、一つ一つ丁寧に変数、関数名を名付け、上司にコードのレビューを出してみました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258740/6c14c814-7e94-4e57-51aa-e7106448dfdd.png" width="200">
上司「もっと良い感じにして」
私（良い感じだと思って名付けたんですけど！！！！！！）

上司は冗長的になると、コードが長くなり読みにくくなるから、良い感じにしてとアドバイスをくれました。
しかし、センスのない私からすると、短くしても長くしてもだめ。良い感じとは人によって違うでしょ！
そもそもセンスない人の良い感じが「良いネーミング」なわけないじゃん！
といった苦しみに苛まれていました。

## チート技
そんな私に上司が教えてくれたことはチート技を使うことです。
codic(https://codic.jp/)
<img width="1423" alt="スクリーンショット 2020-06-04 10.33.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258740/88050448-b720-fcba-9949-27d81e20b5ed.png">

スネークケース、キャメルケースなど言語ごとの命名規則を指定し、ネーミングを生成することが出来ます。

## まとめ
ネーミングセンスがないエンジニアはcodicを使い自信を持ってコードを書きましょう！！！
jbuilderの扱い方

#前提条件
以下のブログを読んでから本記事をお読みください
[非同期通信の手始め](https://qiita.com/Nyanmaru-12/items/70ab49e7a4000085d72b)
[respond_toについて](https://qiita.com/Nyanmaru-12/items/7bc3daf59963c269cf36)

#jbuilder
結論、jbuilderを用いるとrender json 〇〇をしなくていいです。
jbuilderは、viewと同じように該当するアクションと同じ名前にする必要があります。
今回はコメント機能の非同期通信を実装するので
commentのcreateアクションに対応するjbuilderのファイルを作成します。
作成する場所はviews/comments/create.json.jbuilderになります。

```javascript
  json.text  @comment.text
  json.user_id  @comment.user.id
  json.user_name  @comment.user.nickname
```
このような形で記述します。
とても見やすいですよね。jbuilderの最大のメリットは
見やすく分かりやすくコードがかけることです。
積極的に使っていきましょう。
iOSのダウングレード手順

iOSのダウングレード手順を説明します。

`iTunes`がなくなったので、`Finder`から行います。

iOS FW(ips)を以下からダウンロードします。ダウングレードできるバージョンは、`Signed IPSWs`のみ有効です。

https://ipsw.me/

次に、`Finder`を開いて、ダウングレードしたいデバイスを選択します。

次に、macの場合は、`option(alt)`を押しながら、winの場合は`shift`を押しながら`アップデートを確認`ボタンをクリックします。

![](https://raw.githubusercontent.com/mba-hack/images/master/ios_fw_ips_downgrade_01.png)

すると、ファイルを選択できるようになるので、先ほどダウンロードした`.ips`を選択して、ダウングレードできます。
【UiPath】Outlookのメールを取得


# 概要

使用バージョン：UiPath.Mail.Activities v1.8.5


「Outlook メール メッセージを取得」アクティビティを使う。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/83517d67-675b-33d3-abc0-444d5b7f8139.png)

公式ドキュメント：https://docs.uipath.com/activities/lang-ja/docs/get-outlook-mail-messages

# プロパティ
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/de2edae2-0663-2edf-ef3d-1a8ed658e446.png)

**入力**
アカウント - Outlookに設定されているアカウント(メールアドレス)。
メールフォルダ- 「受信トレイ」などのフォルダ名。サブフォルダも指定したい場合は「受信トレイ\フォルダ名」のように\区切りで指定可能。

**オプション**
フィルター - Jet構文、またはDASL構文を使用する。


## フィルターの構文

下記参照(このアクティビティでは、メールのみの検索で予定は検索できない(はず))。
[【Outlook VBA】メールや予定をフィルターで検索する - Qiita](https://qiita.com/vicugna-pacos/items/977fd4c32ebe0486869b)

## 出力
メッセージ `List<MailMessage>` - 見つかったメールのリスト。

出力結果は複数件ある場合があるので、基本的には「繰り返し(コレクションの各要素)」を使って後続処理を行う。その際、「繰り返し」アクティビティのプロパティ「TypeArgument」を「`System.Net.Mail.MailMessage`」にすると扱いやすい。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/40cb4aef-ea07-6f53-fde9-91f46e502f69.png)

# 共有されているアカウントを指定する場合
Office365で、自分に共有メールボックスなどの参照権限がある状態で、その共有されている方のフォルダを参照したい場合の例。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/e795041e-88ca-50ea-acb7-97e8ffd290de.png)

アカウント - 共有されたアカウント。メールアドレスではなく、Outlookに表示されている名前を指定する。
メールフォルダ - `受信トレイ` など自分のアカウントの場合と同じように指定できる。
WPFでインストーラを作ったけど，アプリが起動しなくて死にそうになった件

## インストーラ作成
以下のウェブサイトとかを参考にインストーラを作りました
[VisualStudio 2019 インストーラの作成方法](https://knkomko.hatenablog.com/entry/2019/09/15/033608)
[How to Create Setup.exe in Visual Studio 2019 | FoxLearn](https://www.youtube.com/watch?v=fehVTLNQorQ)

## インストーラを作成して，インストール後，事件が....

アイコンクリックしてもアプリ起動せんやん！！なんでや😭

## 解決
exeやdillファイル意外にも起動に必要なファイルがある場合は，自分で追加しないといけないらしい.
自分の場合は，xmlで情報を管理してたので，そこらへのファイルをインストーラに追加する必要があった．

ファイルの追加は，右クリック→Add→ファイルから選択できます
<img width="1338" alt="Screenshot 2020-06-04 10.08.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181094/82730fb4-e941-96d1-8c18-6e647aeb5b0e.png">

Windowsアプリの情報ネットに乗ってなさすぎ...
Webの世界に戻りたい
子要素にopacityを継承させたくないとき

背景にopacityをかけて透過させたいけどその上に配置する要素は透過させたくない、こんなシーン結構あるはず。

<p class="codepen" data-height="482" data-theme-id="dark" data-default-tab="result" data-user="ririli" data-slug-hash="GRpXdaG" style="height: 482px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="opacity-sample">
  <span>See the Pen <a href="https://codepen.io/ririli/pen/GRpXdaG">
  opacity-sample</a> by ririli (<a href="https://codepen.io/ririli">@ririli</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


サンプルのid=background1は失敗して上に配置する子要素まで透過してしまってます。
opacity-cancelというidでpタグだけなんとかopacityをなかったことにしようとしていますがうまくいっていませんね。

# なんでうまくいかんの？

実はopacityプロパティは該当の要素の子要素全てにopacityを適用させてしまいます。
これだけならcolorなんかと同じですが、決定的な違いがあります。
実は子要素にとってのopacity1=親要素のopacity設定値になってしまうのです。

そのため、子要素側でopacityをunsetにしてもopacity1の状態がそもそも薄くなってしまっているので効果がないわけです。

# どうすればいいわけ？

opacityの代わりにrgbaで透明度を操作します。
これがサンプルのid=background2のパターンです。
元のbackground-corolo:#aaaaaaを変換して全て170に、opacityに設定していた0.3をAlphaにします。

これによって透明度の情報はこの要素のみに適用され、子要素は何も影響を受けません。
Rails6のAPIモードでGraphQLを使う方法(エラー対策も含む)

##はじめに
railsでGraphQLを使うための方法をまとめてみました。

必要最低限の実装にとどめ、GraphQLの動作確認ができることをメインに紹介します。(+αでエラーの対策を記載しました。)
そのため、Queryの設定はしていません。


【参考】
[Rails APIモードで始めるGraphQL](https://qiita.com/dkawabata/items/4fd965ee6d7295386a8b)
[【Rails】graphql-rubyでAPIを作成](https://qiita.com/k-penguin-sato/items/07fef2f26fd6339e0e69)
##アプリ作成
```:ターミナル 
$ rails new demo-graphql --api       #オプションで--apiをつけるとAPIモードでappを作成
```

Gemfileに`graphql`, `graphiql-rails`(開発環境で使用)を追加

```rb:Gemfile
gem 'graphql'    #追加

group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'graphiql-rails'   #開発環境に追加
end
```

コメントアウトを外す

```config/application.rb
require "sprockets/railtie"    #コメントアウトを外す
```

ターミナル で下記を実行

```:ターミナル 
$ bundle install
$ rails generate graphql:install   #GraphQLに関するファイルが作成されます
```

`routes.rb`に下記を追加

```routes.rb
Rails.application.routes.draw do
  if Rails.env.development?
    # add the url of your end-point to graphql_path.
    mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql" 
  end
  post '/graphql', to: 'graphql#execute'  #ここはrails generate graphql:installで自動生成される
end
```

##動作確認
rails sした後に`http://localhost:3000/graphiql`に接続。(graphqlではなくgraphiqlと"i"が入っているので注意してください。上記のroutesで変更しています。)
下記の画面になれば接続成功！
![スクリーンショット 2020-06-03 19.59.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497683/3c207e07-838f-37b5-2560-e6d818911179.png)

試しにQueryを送ると設定をしていないのでエラーが返ってきます。
![スクリーンショット 2020-06-03 19.59.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497683/9734a888-04f0-fd19-fc4b-8a6dfa77b052.png)


##GraphiQLに接続できない場合(Sprockets::Rails::Helper::AssetNotPrecompiled in GraphiQL::Rails::Editors#show)
どの記事を見ても上記の設定しか紹介されておらず、そのまま実装してもエラーが出たので対策方法を紹介します。
APIモードで作成するとassetsが作成されないのでそれが原因のようです。
[[Rails6][sprockets4.0.0]Sprocketsを無効にするためにapp/assetsフォルダ以下を削除すると、Sprockets::Railtie::ManifestNeededErrorが出た](https://qiita.com/dkawabata/items/4fd965ee6d7295386a8b)

どちらかをやれば大丈夫なので開発環境に合わせて選択してください。

エラー内容↓
![スクリーンショット 2020-06-04 10.03.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497683/21fbf8d6-975c-620d-828a-96b34e87dbc4.png)


###対策① assets/config/manifest.jsを作成する
assets/config/manifest.jsファイルを作成し、下記を記載する。


```assets/config/manifest.js
//= link graphiql/rails/application.css
//= link graphiql/rails/application.js
```


###対策② gem 'sprocket'のバージョン3.7.2に下げる
sprockets4.0.0になってからassetsファイルがないとエラーが出るようです。

なのでバージョンを下げると解消できます。

```rb:Gemfile
gem 'sprockets', '~> 3.7.2'  #追加する
```

```:ターミナル 
$ bundle update
```


##終わりに
今回はrails6でGraphQLを使えるようにすることにフォーカスを当てました。
実際にQueryを作成してデータを受け取るところは他の記事を参考にしてください。
【GCP】GAEに登録したサービスの停止

・GAEでは特定のサービスを簡易的に停止できない。
・バージョンがAuto Scaled以外（Manual Scaled,Basic Scaled,GAE Flex）であれば、Cloud Console もしくは gcloudコマンドでバージョンがストップ可能。コマンドは以下URLをみる
https://cloud.google.com/sdk/gcloud/reference/app/versions/stop
・なので、全てのバージョンがAuto　Scaleではない場合は、バージョンを全てで停止することでサービスへアクセスできなくなる。

停止したらちゃんと有効化しよう。
そうしないと次作った時エラーになる。
gcloud app deploy app.yaml --project xxxxx
ERROR: (gcloud.app.deploy) Unable to deploy to application [project] with status [USER_DISABLED]: Deploying to stopped apps is not allowed.

【参考URL】
https://qiita.com/sky0621/items/d89c7473fd5207edcfd5
laravel 値があった場合のみバリデーション


##例: urlは 必須ではなく、入力された場合のみ実行したい

##方法: nullableをつける

```
public function rules()
{
    return [
        ....
        'url' => 'nullable|url|max:255',
    ];
}

public function messages()
{
    return [
        ....
        'url.max'  => ':urlの形式で入力してください',
    ];
}
【Swift】複数行の標準入力の値を取得する

Swiftでpaizaの問題を解くにあたって複数行の標準入力を取得しなければならない場面があり、ググりまくったものの

```swift
var input_lines = [String]()
let row = 3  
for i in 0..<row {
    input_lines.append(readLine()!)
}
print(input_lines) 
```

こんなような決め打ちのコードしか出てこなかったので初心者なりに考えてコード書いてみました。

# 本題
```swift
var lines = [String]();//文字列でない場合はここの方を変える
while true {
  let str:String? = readLine()//ここも文字列でない場合は型を変える
  if let str = str{
    lines.append(str)
  }else{
    break
  }
}
print(lines)
```

このコードであれば、例えば

```
Hello
World
```

のような2行の標準入力でも3行でも100行でも対応できます。

ただし

```
Hello World
This is a pen
```

このような一行に複数の値が存在する場合は

```swift
str.components(separatedBy: " ")
```
を使うなどして文字列を分割して配列にappendすることをお勧めします。
ECS ローリングアップデート

#前提
ローリングアップデートの流れを書いていきます。

#本題

#クラスター作成
EC2 Linux + ネットワーキングを選択
↓
クラスター名を任意の名前を入力
↓
EC2インスタンスタイプ t3.smail
↓
インスタンス数 2
↓
キーペア（作成済みのもの）
↓
VPC・サブネット選択
↓
その他はdefault
↓
作成

#クラスターの上にサービスやタスクを作成

新しいタスク定義
↓
起動タイプはEC２
↓
タスク定義名入力
↓
タスクロール選択（作成済みのもの）
↓
ネットワークモード（bridge）
↓
タスク実行 IAMロール選択
↓
タスクメモリ 512
CPU 512
↓
コンテナ追加
↓
コンテナ名入力
↓
イメージはECRにアップロードしているコンテナのURIを貼り付ける
↓
ポートマッピング
ホストポート：０
コンテナポート：８０
ランダムなポート番号が割り当てられる。
↓
作成

#コンテナ用のロードバランサー作成
ロードバランサーの作成
↓
アプリケーションロードバランサーの作成
↓
名前入力
↓
スキームがインターネット向けになっているか確認
（インターネットからの通信を受け付けるため）
↓
リスナー
HTTP：８０
↓
新しいセキュリティグループ
↓
ターゲット名入力
↓
作成

ターゲットグループが空の状態のロードバランサーの作成完了。

#コンテナデプロイ
クラスター
↓
作成
↓
起動タイプ　EC2
↓
タスク定義は同じもの
↓
サービス名の入力
↓
サービスタイプ　REPLICA
↓
タスク数　４
↓
次のステップ
↓
アプリケーションロードバランサーを選択
↓
IAMロールの選択
↓
ロードバランサーの追加
↓
プロダクションリスナーポート 80:HTTP
↓
ターゲットグループ名選択
↓
サービスの検出の統合の有効化のチェックを外す
↓
次のステップ
↓
サービスの作成

#ロードバランサーがコンテナに通信できない理由
EC2インスタンスにアタッチされているセキュリティグループ、ロードバランサーからの通信許可設定がされていないため

#バランシングチェック
きちんとロードバランシングされているか確認

コンテナインスタンスに対してsshでログイン。
※セキュリティグループに許可グループを追加
↓
設定していたhtmlファイルなどを編集。
↓
リロードして変更が反映されているか確認。

#タスク定義の更新

新しいリビジョンの確認
↓
コンテナイメージのURIを貼り付け
↓
残りの項目は変更なし
↓
作成
↓
作成したタスクをデプロイ
↓
クラスターを開く
↓
更新するサービスの左側のチェックボックスをチェック
↓
リビジョンナンバーを最新のものに設定
↓
次のステップ
↓
サービスの更新

#タスクをオートスケーリング
クラスターの更新するサービス名の左側のチェックボックスにチェックを入れ、更新
↓
オートスケーリングの部分だけ変更
↓
タスクの最小値１
タスクの最大値８
↓
スケーリングポリシーの設定
↓
・ターゲットの追跡　＝　例えば、エアコンの設定温度が２０度の場合、室内温度が２０度に保つように上下左右しながら２０度を保つようなこと
・ステップスケーリング　＝　CPUの使用率が閾値を超えたらタスクを1つ追加すること
↓
次のステップ
↓
サービスの更新
↓
サービスの表示
VSCode Insiderでssh接続時にパスワードループに入ってしまう

エラーの中から以下の文章を見つける

Using commit id {xxxxx} and quality "insider" for server

xxxxがログファイルのディレクトリ名になる。

コンソールからsshでログインし、

home/{user}/.vscode-server-insiders/bin

にあるxxxxxが該当するログファイルなので、rm -rで削除する
サブドメインとサブディレクトリの使い分けのはなし。SEOについても

下記を参考にしています
[SEOで有利なのは個別のドメイン？それともサブドメイン？](https://service.plan-b.co.jp/blog/seo/13835/)
SEO的にはあまり、区別なさそう
サブドメインは大きな分類でサブディレクトリは小さな分類でという感じでしょうか？
※上記をよんでの自分の見解です
laravel nginxでroot以外のページがNot Foundになってしまうとき、これをconfに書く。


dockerでngixを追加してやってみたときの話。
rootのいつものLaravelの画面は出るが、追加したURLでNot Foundになってしまう。


404 Not Found
	nginx/1.19.0

解決策

```try_files $uri $uri/ /index.php?$query_string;```を書く

```bash:nginx/default.conf

server {
  listen 80;
    index index.php index.html;
    root /var/www/public;

  location / {
    root /var/www/public;
    index  index.html index.php;
    try_files $uri $uri/ /index.php?$query_string; # <==
  }

```


nginxのconfにこれがないと/以外のときNot foundになる。

dockerでnginxでやろうと思ってやるとはまる。
"Docker Laravel"で検索したページでもここを強調して書かれているところはないと思うので書きました。

公式に書いてました。

参考
[Installation \- Laravel \- The PHP Framework For Web Artisans](https://laravel.com/docs/7.x)
fatal: 'origin/hoge_branch' is not a commit and a branch 'hoge_branch' cannot be created from it

特定のリモートブランチをcheckoutしたくてこれをやるとこのエラーになる。

```bash
git checkout -b hoge_branch origin/hoge_branch
fatal: 'origin/hoge_branch' is not a commit and a branch 'hoge_branch' cannot be created from it

# しばし悩んで、ローカルはリモートブランチ名を知らないことに気づく
git fetch

git branch -a
* master
  remotes/origin/hoge_branch

# これでチェックアウトできる
```
dockerfileで親ディレクトリを参照したい！

# はじめに
会社の研修で詰まったところをメモ程度に書いていく

## やりたかったこと
以下のようなディレクトリ構造の時、dokerfileから親ディレクトリのindex.htmlをCOPYしたかった

```:ディレクトリ構造
content/
 │
 ├ .infrastructure/
 │   ∟ dockerfile
 │
 ├ files/
     ∟ index.html
```


```dockerfile:dockerfile
FROM: nginx:latest
COPY: ../files/ /usr/share/nginx/html
WORKDIR /usr/share/nginx/html
```

これで.infrastructureディレクトリで `docker build`を実行。

### 実行結果

```bash
.infrastructure $ docker build . -t docker-html
--　実行結果 --
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM nginx:latest
 ---> 9beeba249f3e
Step 2/2 : COPY ../files/  /usr/share/nginx/html
COPY failed: Forbidden path outside the build context: ../files/ ()
```
このように`COPY failed: Forbidden path outside the build context: ../files/ ()`と表示され親ディレクトリを参照できない

## 解決方法
-f オプションを使って、`content`ディレクトリから`docker build`コマンドを実行する
以下の通り

```bash
# docker build -f [dockerfileの指定] -t [イメージ名] [イメージを作成する時に参照するディレクトリ]
$ docker build -f .infrastructure/dockerfile -t image_name .
```

### 注意点
最後の`.`忘れないように！　
今回の場合はカレントディレクトリからimageを作成するため`.`。

# まとめ
dockerfileから別のディレクトリのファイルを参照することはできない。
なので、親ディレクトリから-fオプションを用いてコマンドを実行すれば良い。
【新入社員向け】情報セキュリティ基礎

# 情報セキュリティについて

### 目次
1. 情報セキュリティとは
2. 脆弱性とは

## 1. 情報セキュリティとは
情報セキュリティとは、Webサービスにおいてのセキュリティ**(安全保障)**です。
情報セキュリティにおける理想は、「不正なアクセスや情報の漏洩を防ぎつつ、権限がある人は便利に利用できる」状態を維持することです。
これを分解し言い換え、**「機密性」** **「完全性」** **「可用性」**の3つの要素を維持することを目標にします。

#### 「機密性」

- 権限を持たない人が情報資産を見たり使用できないようにすること<br>
（アクセス権限を関係者に限定し、パスワードをかけて関係者しか開くことができなくすること）


#### 「完全性」
- 権限を持たない人が情報を書き換えたり消したりできないようにすること<br>
（WEBサイトの改ざん・データの改ざんがされないこと）

### 「可用性」
- 権限を持つ人がいつでも利用したいときに利用できるようにすること<br>
（テレワーク等で社外からでも必要な情報を利用できるようにすること）

## 2. 脆弱性とは
脆弱性とは、コンピュータやネットワーク、アプリケーション全体のセキュリティに弱点を作り出すコンピュータソフトウェアの欠陥や仕様上の問題点のことをいいます。
つまり、アプリケーション上で悪意のある者に攻撃を仕掛けられる際の弱点になります。
また、開発者側だけでなく、利用者側も被害を被る可能性があるので、脆弱性対策は必須です。
脆弱性は、バグや、開発者のセキュリティチェック不足により生まれます。

### 脆弱性によってもたらされる被害

- 個人情報を勝手に閲覧される(機密性侵害)
- Webページの内容が改ざんされる(完全性侵害)
- Webページ自体が利用不能になる(可用性侵害) このような問題が起きてしまうと、利用者への金銭的損失の補填や補償、開発者の社会的信頼の失墜による売上の減少、
Webサイト停止による機会損失など多くの被害を開発者だけではなく利用者も被ることになるため脆弱性対策は必須となります。
Redmine on Docker

#はじめに

本記事は動画( https://youtu.be/-DrdYw8fHwc )で説明に使用している
スライドを記事化したものです。動画と合わせて御覧ください。
[![-DrdYw8fHwc](http://img.youtube.com/vi/-DrdYw8fHwc/0.jpg)](http://www.youtube.com/watch?v=-DrdYw8fHwc)

※記事化する際に補足説明を加筆しており、内容は動画のスライドと異なります。
※本記事の内容は2020年3月時点の内容となります。OSやミドルウェア、Dockerのバージョンが異なることで記載通りの内容で完了しない場合があります。

---

#ミドルウェア構成

   1. OS		： CentOS 7.8
   2. Webサービス	： Apache 2.4.6
   3. アプリ言語	： Ruby 2.4
   4. DBサービス	： MariaDB 10.4.3
   5. Redmine		：  Redmine 4.1
 
---

#Dockerfileで下準備

```Dockerfile
# centos7のイメージを利用する
FROM centos:7
LABEL maintainer=Takemi

SHELL ["/bin/bash", "-o", "pipefail", "-c"]"

# 累積アップデートの実行
RUN yum -y upgrade

#takemiユーザが存在していない場合ユーザ追加する
RUN echo 'make user takemi'
RUN adduser -m takemi;echo "takemi:takemi123" | chpasswd;

#sshのインストール
RUN yum install -y openssh-server
RUN systemctl enable sshd

#Apacheのインストール
RUN yum install -y httpd
RUN systemctl enable httpd

#MariaDBのインストール
RUN curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash
RUN yum install -y MariaDB-server MariaDB-devel MariaDB-shared
RUN systemctl enable mariadb

#ruby インストール準備
RUN yum -y groupinstall "Development Tools"
RUN yum -y install openssl-devel readline-devel zlib-devel curl-devel libyaml-devel libffi-devel
RUN yum -y install httpd-devel
RUN yum -y install ImageMagick ImageMagick-devel ipa-pgothic-fonts
WORKDIR /root
RUN curl -O https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.1.tar.gz
RUN tar xf ruby-2.4.1.tar.gz
WORKDIR /root/ruby-2.4.1
RUN ./configure --disable-install-doc
RUN make
RUN make install
RUN gem install bundler --no-rdoc --no-ri
```

```cmd
		> docker build -t redmine .
```

### Dockerfileでやってること！
1. OSのイメージ構築
2. OSのアップデート
3. ルートユーザパスワード発行
4. 一般ユーザ作成、パスワード発行
5. sshのインストール
6. Apacheのインストール
7. MariaDBのインストール
8. Rubyのインストール

---

#DBの設定

DBのrootユーザの追加

```
root > mysql
mysql > GRANT ALL PRIVILEGES ON *.* TO 'takemi'@'localhost' IDENTIFIED BY 'takemi123' WITH GRANT OPTION;
mysql > FLUSH PRIVILEGES;
```

※DBのユーザ名とOSのユーザ名を合わせておくと、OSのログインユーザがmysqlコマンドを実行する時にユーザ名指定を省略することができるようになります。

---

#Redmineのインストール

```
root > cd /var/www
root > svn co https://svn.redmine.org/redmine/branches/4.1-stable redmine-4.1
user > cd redmin-4.1
user > cd config
user > cp configuration.yml.example configuration.yml
user > cp database.yml.example database.yml
user > vi database.yml
	username: takemi
	password: "takemi123"

root > cd /var/www
root > chown -R takemi:takemi redmine-4.1
root > vi /etc/group
	takemi:x:1000:apache

root > cd /var/www/redmine-4.1
root > gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'
root > bundle install --without development test --path vendor/bundle
root > bundle exec rake generate_secret_token
root > gem install passenger --no-rdoc --no-ri
root > passenger-install-apache2-module --auto
root > passenger-install-apache2-module --snippet
root > vi /etc/httpd/conf.d/redmine.conf
root > systemctl restart httpd

user > mysql -p
	create database redmine default character set utf8;
user > RAILS_ENV=production bundle exec rake db:migrate
user > RAILS_ENV=production REDMINE_LANG=ja bundle exec rake redmine:load_default_data


```

#Redmineのセットアップ

ブラウザでアクセス！
詳しくは動画で！
rbenvでRubyのバージョン切り替え

＃ 環境
macOS Catalina 10.15.4
rbenv
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]

現在インストールされているRubyバージョンよりも新しいものを使いたかったのでrbenvにてバージョンを切り替えます。

```sh
// rbenv本家にも書いてありますが初期化が必要です。ログイン時に済ませるためbash_profileに書いておきます
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

// rbenvをインストールするとruby-buildは依存関係解決でinstallされた思いますが念のため指定
$ brew install rbenv ruby-build

// install可能なバージョンを一覧
$ rbenv install -l
2.5.8
2.6.6
2.7.1
jruby-9.2.11.1
maglev-1.0.0
mruby-2.1.0
rbx-4.15
truffleruby-20.1.0

// install
$ rbenv install 2.7.1

// この時のrbenv経由のrubyのPATHはそれ以前のものを参照している。つまりこの時点のバージョンは2.6.3
$ rbenv which ruby
/usr/bin/ruby

// rbenvでないrubyの方はちゃんとrbenvのrubyをみている
$ which ruby
/Users/your_account/.rbenv/shims/ruby

// local（今いるディレクトリ）に反映の場合
$ rbenv local 2.7.1

// shimsに反映
$ rbenv rehash

$ rbenv which ruby
/Users/your_account/.rbenv/versions/2.7.1/bin/ruby
```

以上
浮動小数点数の問題をどう回答するか

AtcoderのABC１６９にて素晴らしい問題が出ました。
浮動小数点数に関する問題です。

##業務では
業務では「decimal型」を使用しています。
実際の製品開発では処理速度がいらないなら、動作の安定したフレームワーク、ライブラリを使うのが正解です。
ミスを少なく、素早く組めるとは素晴らしいです。
人件費削減＝利益率です。

##競技プログラミングでは
タイムアタックである以上、直感で組めることは大事です。
これからは「decimal型」がさっと使える言語で回答します。
流行ではpythonかなと思います。
C#はマイクロソフト環境なのでmac使いの自分には向いていないのと求人の数が少ないです。

###[B - Multiplication 2](https://atcoder.jp/contests/abc169/tasks/abc169_b)
問題文はAtCoderを参照してください。

```C++:C++
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<utility>
#include<iomanip>
#include<map>
#include<cmath>
#include<cstdio>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define pai 3.1415926535897932384
 
using namespace std;
using ll =long long;
using P = pair<int,int>;
 
#define INF 1000000000000000000
//1000000000000000000
//2147485794483647
int main(int argc, const char * argv[]) {
    ll n;
    cin >> n;
    
    unsigned long long ans=1;
    rep(i, n){
        unsigned long long m;
        cin >> m;
        if(m==0) ans = 0;
        else if(ans>INF/m) ans=INF+1;
        else ans = ans * m;
    }
    
    if(ans>INF) cout << -1;
    else cout << ans;
    
    return 0;
}
```

```python:python
N = int(input())
A=list(map(int, input().split()))
 
ans=1
c=0
 
while c<N:
    if A[c]==0:
        ans=0
    elif ans*A[c]>1000000000000000000:
        ans=1000000000000000001
    else :
        ans=ans*A[c]
    
    c+=1
    
if ans>1000000000000000000: print(-1)
else: print(ans)
```

###[C - Multiplication 3](https://atcoder.jp/contests/abc169/tasks/abc169_c)
問題文はAtCoderを参照してください。

```C++:C++
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<utility>
#include<iomanip>
#include<map>
#include<cmath>
#include<cstdio>

#define rep(i,n) for(int i=0; i<(n); ++i)
#define pai 3.1415926535897932384

using namespace std;
using ll =long long;
using P = pair<int,int>;

int main(int argc, const char * argv[]) {
    ll a;
    string b;
    cin >> a >> b;
    
    for(ll i=b.size()-1; i>=0; i--){
        if(b[i]=='.'){
            b.erase(i, 1);
        }
    }
    long long bb = stoi(b);
    a = a * bb;

    cout << a / 100;
    return 0;
}
```

```python:python
from math import floor
from decimal import Decimal

A, B = list(input().split())

ans = int(A) * Decimal(B)

print(floor(ans))
```
Node.js: mysql2 で MariaDB のデータを削除 (Delete)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_mariadb.js
├── go_delete.sh
└── maria_delete.js
```

Async/Await を使います。

```js:maria_delete.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	maria_delete.js
//
//					Feb/24/2023
//
// ---------------------------------------------------------------
'use strict'

var mysql = require('mysql2')
var config_mariadb = require('./config_mariadb')
// ---------------------------------------------------------------
async function main(id_in)
{
	const [host, user, password, data_base] = config_mariadb.config_mariadb_proc()
	var conn = await mysql.createConnection ({
		host: 'localhost',
		user: user,
		password: password,
		database: data_base
		})

	const command = "delete from cities where id = '" + id_in + "'"

	await conn.execute(command)
	conn.end()
	console.error ("*** 終了 ***")
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
const id_in = process.argv[2]
console.log (id_in)
main(id_in)
// ---------------------------------------------------------------
```

.env
config_mariadb.py
はこちら
[Node.js: MariaDB のバージョンを表示](https://qiita.com/ekzemplaro/items/8ee5003528370719f3ea)

実行コマンド

```bash:go_delete.sh
export NODE_PATH=/usr/lib/node_modules
./maria_delete.js t3327
```

## 確認したバージョン

```text
$ node -v
v19.7.0
```
Node.js: mysql2 で MariaDB のデータを更新 (Update)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_mariadb.js
├── go_update.sh
└── maria_update.js
```

Async/Await を使います。

```js:maria_update.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	maria_update.js
//
//					Feb/24/2023
//
// ---------------------------------------------------------------
'use strict'

var mysql = require('mysql2')
var config_mariadb = require('./config_mariadb')
// ---------------------------------------------------------------
function get_current_date_proc ()
{
	const today = new Date ()
	var ddx = (1900 + today.getYear ()) + "-" + (today.getMonth () +1)
	ddx += "-" + today.getDate ()

	return ddx
}

// ---------------------------------------------------------------
function update_command_gen (id_in,population_in)
{
	const today = get_current_date_proc()
	var command = "update cities set population = " + population_in
	command += " , date_mod = '" + today + "'"
	command += " where id = '" + id_in + "'"
	console.log (command)

	return	command
}

// ---------------------------------------------------------------
async function main(id_in,population_in)
{
	const [host, user, password, data_base] = config_mariadb.config_mariadb_proc()
	var conn = await mysql.createConnection ({
		host: host,
		user: user,
		password: password,
		database: data_base
		})

	const command = update_command_gen (id_in,population_in)

	await conn.execute(command)
	conn.end()
	console.error ("*** 終了 ***")
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")

const id_in = process.argv[2]
const population_in = process.argv[3]

console.log (id_in + "\t" + population_in)

main(id_in,population_in)
// ---------------------------------------------------------------
```

.env
config_mariadb.py
はこちら
[Node.js: MariaDB のバージョンを表示](https://qiita.com/ekzemplaro/items/8ee5003528370719f3ea)


実行コマンド

```bash:go_update.sh
export NODE_PATH=/usr/lib/node_modules
./maria_update.js t3326 721539800
```

## 確認したバージョン

```text
$ node -v
v19.7.0
```
Node.js: mysql2 で MariaDB のデータを読む (Read)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_mariadb.js
├── go_read.sh
└── maria_read.js
```

Async/Await を使います。

```js:maria_read.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	maria_read.js
//
//					Feb/24/2024
//
// ---------------------------------------------------------------
'use strict'
var mysql = require('mysql2/promise')

var config_mariadb = require('./config_mariadb')
// ---------------------------------------------------------------
function compare_by_key_proc (left,right)
{
	var aa = left.key
	var bb = right.key

	var rvalue = 0

	if (aa < bb)
		{
		rvalue = -1
		}
	else if (aa > bb)
		{
		rvalue = 1
		}

	return	rvalue
}

// ---------------------------------------------------------------
function sort_key_proc (dict_aa)
{
	var array = new Array()

	for(var it in dict_aa)
		{
		array.push({'key':String (it), 'value':dict_aa[it]})
		}

	array.sort (compare_by_key_proc)

	return array
}

// ---------------------------------------------------------------
function dict_display_proc (dict_aa)
{
	const array_aa = sort_key_proc (dict_aa)

	array_aa.forEach (function(unit_aa,index)
		{
		const key = unit_aa.key
		const value = unit_aa.value

		var out_str = key + "\t"
		out_str += value["name"] + "\t"
		out_str += value["population"] + "\t"
		out_str += value["date_mod"]
		console.log (out_str)
		})	
}

// ---------------------------------------------------------------
async function read01 (mysql,host,user,password,data_base)
{
	try {
		var conn = await mysql.createConnection({
			host: host,
			user: user,
			password: password,
			database: data_base
			})
		const sql_str = 'select * from cities'
		const [rows, fields] = await conn.execute(sql_str)

		return rows
	} catch (ee) {
		console.log(ee)
		return ''
	} finally {
		if (conn && conn.connection) {
		conn.end()
		}
	}

}

// ---------------------------------------------------------------
async function main()
{
	const [host, user, password, data_base] = config_mariadb.config_mariadb_proc()
	const rows = await read01 (mysql,host,user,password,data_base)

	var dict_aa = new Object ()

	rows.forEach(function(row)
		{
		dict_aa[row.id] = {"name": row.name,
			"population": row.population,
			"date_mod": row.date_mod}
		})

	dict_display_proc (dict_aa)

	console.error ("*** 終了 ***")
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
main()
// ---------------------------------------------------------------
```

.env
config_mariadb.py
はこちら
[Node.js: MariaDB のバージョンを表示](https://qiita.com/ekzemplaro/items/8ee5003528370719f3ea)

実行コマンド

```bash:go_read.sh
export NODE_PATH=/usr/lib/node_modules
./maria_read.js
```

## 確認したバージョン

```text
$ node -v
v19.7.0
```
Node.js: mysql2  で MariaDB のデータを作成 (Create)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_mariadb.js
├── go_create.sh
└── maria_create.js
```

Async/Await を使います。

```js:maria_create.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	maria_create.js
//
//					Feb/24/2023
//
// ---------------------------------------------------------------
'use strict'

var mysql = require('mysql2/promise')
var config_mariadb = require('./config_mariadb')
// ---------------------------------------------------------------
function dict_append_proc (dict_aa,id_in,name_in,population_in,date_mod_in)
{
	var unit_aa = {}
	unit_aa['name'] = name_in
	unit_aa['population'] = population_in
	unit_aa['date_mod'] = date_mod_in

	dict_aa[id_in] = unit_aa

	return	dict_aa
}

// ---------------------------------------------------------------
function data_prepare_proc ()
{
	var dict_aa = new Object ()

	dict_aa = dict_append_proc (dict_aa,'t3321','岡山',812763,'1950-10-23')
	dict_aa = dict_append_proc (dict_aa,'t3322','倉敷',783257,'1950-7-15')
	dict_aa = dict_append_proc (dict_aa,'t3323','津山',975241,'1950-1-2')
	dict_aa = dict_append_proc (dict_aa,'t3324','玉野',231864,'1950-6-22')
	dict_aa = dict_append_proc (dict_aa,'t3325','笠岡',769358,'1950-8-14')
	dict_aa = dict_append_proc (dict_aa,'t3326','井原',865792,'1950-9-12')
	dict_aa = dict_append_proc (dict_aa,'t3327','総社',438251,'1950-3-21')
	dict_aa = dict_append_proc (dict_aa,'t3328','高梁',352486,'1950-7-26')
	dict_aa = dict_append_proc (dict_aa,'t3329','新見',246951,'1950-10-2')
	
	return	dict_aa
}

// ---------------------------------------------------------------
async function main()
{
	const dict_aa = data_prepare_proc ()

	const [host, user, password, data_base] = config_mariadb.config_mariadb_proc()
	try {
		var conn = await mysql.createConnection ({
			host: host,
			user: user,
			password: password,
			database: data_base
			})

		const sql_str_drop = 'drop table if exists cities'
		await conn.execute(sql_str_drop)

		var sql_str_create = 'create table cities '
		sql_str_create += '(id varchar(10), name varchar(20),'
		sql_str_create += ' population int, date_mod date)'
		await conn.execute(sql_str_create)

		for (var key in dict_aa)
		{
		console.log(key)
		var sql_str = "insert into cities "
		sql_str += "(id,name,population,date_mod) values ("

	const str_data = "'" + key + "','" + dict_aa[key].name + "',"
		+ dict_aa[key].population + ",'" + dict_aa[key].date_mod + "')"

		sql_str += str_data
		await conn.execute(sql_str)
		}

	} catch (ee) {
		console.log(ee)
		return ''
	} finally {
		if (conn && conn.connection) {
		conn.end()
		}
	}

	console.error ("*** 終了 ***")
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
main ()
// ---------------------------------------------------------------
```

.env
config_mariadb.py
はこちら
[Node.js: MariaDB のバージョンを表示](https://qiita.com/ekzemplaro/items/8ee5003528370719f3ea)

実行コマンド

```bash:go_create.sh
export NODE_PATH=/usr/lib/node_modules
./maria_create.js
```

## 確認したバージョン

```text
$ node -v
v19.7.0
```
rbenvにてreadline, libhistoryがないと言われたときの対処

# 環境
macOS Catalina 10.15.4
rbenv
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]


`brew install rbenv` の後、バージョン確認や `rbenv init`　した際にエラーが出た。

```sh
$ rbenv -v
dyld: Library not loaded: /usr/local/opt/readline/lib/libreadline.6.dylib
  Referenced from: /usr/local/bin/bash
  Reason: image not found
Abort trap: 6
```

readlineはhomebrewで依存関係解決でインストールされているのを確認済みだ。

```sh
$ ls /usr/local/opt/readline/lib/
libhistory.8.0.dylib   libhistory.a           libreadline.8.0.dylib  libreadline.a          pkgconfig/
libhistory.8.dylib@    libhistory.dylib@      libreadline.8.dylib@   libreadline.dylib@
```

`libreadline.6.dylib` から `libhistory.dylib` にシンボリックリンクを張って解決できそうなので

```sh
$ ln -s /usr/local/opt/readline/lib/libreadline.dylib /usr/local/opt/readline/lib/libreadline.6.dylib

$ ls /usr/local/opt/readline/lib/
libhistory.8.0.dylib   libhistory.a           libreadline.6.dylib@   libreadline.8.dylib@   libreadline.dylib@
libhistory.8.dylib@    libhistory.dylib@      libreadline.8.0.dylib  libreadline.a          pkgconfig/

$ rbenv -v
dyld: Library not loaded: /usr/local/opt/readline/lib/libhistory.6.dylib
  Referenced from: /usr/local/bin/bash
  Reason: image not found
Abort trap: 6
```

readlineのエラーがでなくなったがlibhistoryでも同じことが必要っぽいので

```sh
$ ln -s /usr/local/opt/readline/lib/libhistory.dylib /usr/local/opt/readline/lib/libhistory.6.dylib

$ rbenv -v
rbenv 1.1.2
```

解決しました。
[mysql,laravel]あるカラムで重複を持つレコードだけをまとめずに全て呼び出す方法

#何をした？

operationsテーブルから"第三工種"というカラムで重複するレコードに付随しているデータの塊を作りたいと考えました。

具体的には"第三工種"に"土工"というレコードが複数ある場合、それ以降の”第四工種”以降が"埋め戻し"のものや”掘削"のものなどに分岐します。
それを”第三工種に土工を持つもの全て"で一括りの配列にして、呼び出したいと考えました。



（参考）ER図
![v4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555157/f3c9a304-52b7-efaf-e850-410381f7404f.png)

#失敗した方法

ひとことで言うと、クエリによる処理でなく配列処理で対応しようとしたらドツボにはまりました。

######※詳細（分かりにくいので、お急ぎの方は読まなくて大丈夫です）
まずテーブルから全レコードを呼び出し、`distinct()`で重複を絞った後、その"id"を持つ"第三工種"を抜き出します。その"第三工種"のレコードを持つものを`foreach`と`array_keys()`により、`distinct()`してないものと比較することで新しい１次配列を作り、そこからviewに呼び出そうとしました。

→`array_key()`はオブジェクトに対して使えないというエラーで挫折しました。
[コレクション](https://readouble.com/laravel/5.7/ja/collections.html)を使えばいけるかもしれなかったですが、１次配列にしてしまうと呼び出しも厄介なので中断しました。

→代案で"id"を抽出した後、全て入ったデータから`array_column()`でそれぞれのカラムを抜き出して、呼び出しの時に該当のidを使って呼び出すことを考えましたが、`array_column()`もオブジェクトに対して使えないというエラーが出たので中断しました。

#解決方法

下記のsqlをコントローラで書き出して、”第三工種”が同じものだけの配列にまとめることで対応しました。

```sql:sequelproのクエリで実行した記述
SELECT
    operations.id,
    operations.third_operation_class
FROM
    -- サブクエリで件数を取得
    (
    SELECT
        third_operation_class,
        COUNT(third_operation_class) AS CNT
    FROM
        operations
    GROUP BY
        third_operation_class
    ) AS third_operation_class_CNT
-- 自己結合
INNER JOIN
    operations
ON
    third_operation_class_CNT.third_operation_class = operations.third_operation_class
AND
    third_operation_class_CNT.CNT > 0;

```

```
#上記の結果
id  third_operation_class
8	お試し３
9	河川土工
16	土工
17	土工
18	土工
19	土工
20	土工
21	土工
22	土工
```

#その後

この記述で他のカラムも呼び出して、"third_operation_class"が同じものだけでまとめることで、欲しい値だけの配列ができるので、そこにforeachでインデックス番号をふって、そのインデックス番号でページを分けて表示しました。

#参考
https://johobase.com/extracts-duplicate-records-sql/
VBAで他のエクセルファイルのセルに値を入力する

# やりたいこと
ダイアログボックスでエクセルファイルを指定する。
指定したエクセルブックを開き、Sheet1のA1セルに「あああ」という文字を入力する。
上書き保存して閉じる。

# ソースコード
```vb
Sub Enter_text_in_other_excel_file()

'----------ダイアログボックスで指定のエクセルファイルを開く----------

'エクセルファイルのファイルパスを格納する変数FilePathを宣言する
Dim FilePath As String

'ApplicationオブジェクトのGetOpenFilenameメソッドを使って、[ファイルを開く]ダイアログボックスを表示する
'[ファイルを開く]ダイアログボックスに、どんな拡張子のファイルを表示するかを引数FileFilterで設定する
'選択されたファイルのフルパスをFilePathに格納する
FilePath = Application.GetOpenFilename("Microsoft Excelブック,*.xls?")

'GetOpenFilenameメソッドによる[ファイルを開く]ダイアログボックスは選択されたファイルのフルパスを返すだけで、自動的には開かないため、Workbooks.Openを使ってファイルを開く
Workbooks.Open FilePath

'FilePathに代入されているフルパスから、ファイル名を抽出する
'Dir関数は引数に指定したファイルが存在したとき、そのファイル名を返す関数
FileName = Dir(FilePath)

'----------値を入力する----------

'前の処理で抽出したファイルのシートとセルを指定して値を入力する
Dim aaa As String
Workbooks(FileName).Worksheets("Sheet1").Range("A1").Value = "あああ"

'----------上書き保存して閉じる----------

Workbooks(FileName).Save
Workbooks(FileName).Close

End Sub
```
【Day78】積み上げ日記

##学習内容
■関数（復習）
■イベント
■ストップウォッチ作成

##学習ポイント
■関数とは
何かを受け取って、何かを返すもの。
受け取る値；引数
返す値：返り値　
■changeイベント
ユーザーによる値の変更が確定した時に発生する
■onsubmitイベント
フォームを送信する
■preventDefault
フォームの送信を抑制する（入力不備があった場合など）
■日付、時間を取得できる関数
new Date()


##参考記事
■引数とは
https://www.youtube.com/watch?v=5PybPAXs2O8
回路シミュレータ「LTspice」で回路図を書いてみた

## 概要

回路シミュレーション・ソフトウェア LTspice を利用して回路図を作成した。

## はじめに

全くの素人である筆者が最近電子工作に興味を持ち始め、協力者（電子工作歴20年秋葉原歴17年）のアドバイスのもと、秋月電子にて購入したオーディオアンプキットを先日製作した。
![EZPg8-MUYAIzLp5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646713/65a79467-0bcb-e6a4-2071-0b4d003c9887.jpeg)

商品のリンクは以下。

ポータブルヘッドフォンアンプキット　（ケース付フルキット）
http://akizukidenshi.com/catalog/g/gK-03741/

協力者（電子工作歴20年秋葉原歴17年）からの熱心な指導を受けつつはんだ付けや組み立てまでの作業は習得できたが、内部の構造動作原理などはまだ理解していない。（協力者の出身大学では3年次に把握できるようになるらしい）

そのため次のステップとして、構造がシンプルで筆者でも大まかな仕組みを理解出来そうな以下のラジオキットを購入した。

ゲルマラジオキット Crystal Radio 2PK2300
http://akizukidenshi.com/catalog/g/gK-00907/

このラジオキットの制作過程を Qiita にて記事にしていくことを踏まえたうえで、まずはキットに付属している回路図を貼り付けたいのだが、リテラシ及び総合的な学習の目的で LTspice 上にて回路図を書こうと考えた。

## LTspice の導入

LTspice はフリーの回路シミュレーション・ソフトウェアである。
公式サイトからのダウンロードは以下から。
https://www.analog.com/jp/design-center/design-tools-and-calculators/ltspice-simulator.html

## 回路図を書いてみた

LTspice で作成した回路図が下記の通りである。

![dfss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646713/49ed2852-73a4-ca79-7fd7-fe93895221e3.png)

協力者（電子工作歴20年秋葉原歴17年）に適宜手伝ってもらった。それぞれのパーツの意味はまだ把握していないが、仮に把握しきれていればサクサクと線を引くことができるだろう。

今回はここまで。
協力者（電子工作歴20年秋葉原歴17年）からの伝聞は以下の通りである。


(๑•﹏•๑｀)ぷえ〜
初心者によるプログラミング学習ログ 334日目

#100日チャレンジの334日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
334日目は、
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>334日目　1.5h<br>・ポートフォリオ作成<br>モーダルウインドウ実装でいろいろ調べているうちに寝落ちしちゃった<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1268274236772114432?ref_src=twsrc%5Etfw">June 3, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
再度プログラミングの復習

作りたい物のラフ画を箇条書きで表してみました。箇条書きなので見にくかったらすみませんf(^ー^;　

ラフ画を元に表のページを
htmlとcssで書いてみようかと思います。


つまずきそうな点
・padding　
・divで書いてる時のコードの配置等度々間違えそうです…

![Screenshot_20200604-035908_Gallery.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640511/2e065dd2-fccf-ea56-2b3b-e5ae69d25540.jpeg)
[理論で説明？]主成分の分散が共分散行列の固有値って

主成分分析って数学的にちゃんとしてるってのが嬉しい。

> 主成分分析は高い次元のデータを少ない次元へ要約する多変量解析手法のこと。
（[Hotelling, 1933](https://psycnet.apa.org/doiLanding?doi=10.1037%2Fh0071325)）

なわけだが、コツとしてはなるべく元々のデータが持っている情報量を落とさないように次元を下げるということができるってのが魅力。今日はそれで求められるいくつかの事実でとても重要と思う「主成分の分散が共分散行列の固有値と一致する」ことをちゃんと説明してみる（数学的に）。
なので興味ない人はもう読まなくて大丈夫ですｗ

### 主成分の定義

説明が次元の大きさに左右されないようにベクトルや行列の表記も使っていくがとりあえず計算しやすそうな2次元で説明する（2次元で主成分は使わんだろと言われそうなので）。
$\boldsymbol{X}=(X_1, X_2)'$を2次元確率ベクトルとする。この分散共分散行列$\Sigma$を

```math
\Sigma = \begin{bmatrix}
\sigma_1^2 & \sigma_{12} \\\
\sigma_{21} & \sigma_2^2
\end{bmatrix}
```
とする。平均ベクトル $\boldsymbol{\mu}$は $\boldsymbol{0}$として一般性を失わない（w.l.o.g. なぜ？）
このとき、主成分分析では、確率変数の線形結合 $a_1X_1+a_2X_2 (\equiv Y)$を考えて、$(X_1,X_2)$の変動の大きさ（データの持っている情報）を出来るだけ多く取込むように係数を決める。つまり、$Y$の分散が最大になるように$a_1,a_2$の値を決定する。この結果得られた$Y$を**第1主成分**と呼び、これが$(X_1,X_2)$の全変動と比べて情報が不十分であれば(不十分ってどう判断する？)第1主成分と直交する（第1主成分が持っていない情報という意味）新たな線形結合である第2主成分を求めていく。これでも不十分なら第3主成分、、のように続けていけばよい。
あれ？
固有値の話出てきてなくね？
そうなんです。主成分の定義では固有値は全く関係ないのです。定義から主成分を求めていこうとするとこうやって順を追っていかなくてはならない。これが最終的に固有値と繋がるのだからすっきりした話になるわけさな。最近ではこの話がスパースな分析に繋がることになっているがそこでもこの理論展開が威力を発揮している。
あと、ここで定義が終わるが仮定されていることとしてはデータ（標本、sample）が無作為に得られていることであって、**作られる主成分は線形結合**だが、データの関係性は別に線形である必要はない。
これは[主成分分析が非線形データ扱えないっておかしくね？](https://qiita.com/Yh_Taguchi/items/2cbdab3a4e1f8eba8d9e)にも書かれている。これ、多分捉え方のズレが大きくて線形推す人たちってデータに線形関係があれば次元圧縮の観点からは効果的というくらいの意味なのかなと。でも線形関係強いと主成分の解釈難しくなることおおいんじゃねぇのかなとかも思うから線形・非線形はあまり気にしなくてもよいってのが個人的感想。少なくとも定義式見ても問題はない。

この続きでは実際に固有値との関係見ていくが、それは[この記事編集か別の記事](https://qiita.com/nizu708/items/e24d13ec99683e5dd650)で。
【DB設計】No.1「DBのリレーションとER図」

本記事では、DBの基本中の基本であるDBのリレーション（関係）について。
次に、そのリレーションを図ではどのように表現するのかを書いていきたいと思います。
##リレーションとは
リレーションとは簡単に言うと、**テーブル同士の関係性**を表します。
具体的にみてみると、データベースのリレーションには以下の3つの関係性があります。

・**1:n(一対多）**
「会社」と「社員」というテーブルが存在するとき、**1つの会社に複数人の社員が存在する**ので、この両者の関係は1：nになっていると言えます。

・**n:n（多対多）**
「サークル」と「社員」というテーブルが存在するとき、**1人の社員は複数のサークルに所属する**ことができます。そして、**サークルには複数の社員が存在**します。
よってこの両者の関係はn:nになっていると言えます。

※n:nの場合、中間テーブルを用いてDBを構成します。詳しくは後ほど説明します。

・**1:1**
「社員」と「個人情報」というテーブルが存在するとき、**1人の社員は1つの個人情報**を持っています。
よってこの両者の関係は1：1になっていると言えます。

##ER図の書き方
まずER図には原則として以下の決まり事があります。
これを元にER図を書いていきます。
<img width="717" alt="スクリーンショット 2020-06-04 3.00.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618902/c69ef682-1b79-8237-8938-3edb290bc572.png">
出典：https://it-koala.com/entity-relationship-diagram-1897#ER-4

##ER図の例
**・1：1**
2つのテーブルを直線で繋ぎ、1の関係を表す縦棒「|」を書き加えます。
<img width="557" alt="スクリーンショット 2020-06-04 3.03.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618902/b3e9206b-24fb-f495-e350-ed703da9002c.png">

**・1：n（1：1以上）**
nの関係にあたるテーブルに対して鳥の足を書き加えます。
<img width="570" alt="スクリーンショット 2020-06-04 3.05.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618902/06a0471b-9725-d535-f8ee-0b3f13f3b142.png">

**・n:n（0を含む）**
サークルは作ったけれども社員がいない場合や、社員がサークルに所属しない場合も考慮して、図のように0を表す○を鳥の足に書き加えます。
<img width="562" alt="スクリーンショット 2020-06-04 3.09.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618902/f6a00b21-d665-308a-a1b0-c39a021ac457.png">

##中間テーブル
以下のようなn:nのリレーションが成り立つテーブルがあるとします。
このとき、userがcourseを持たない時（逆も然り）、無駄なカラムを持つことになります。
このようなDB設計はアンチパターンと言われ、好ましくない設計となります。
<img width="571" alt="スクリーンショット 2020-06-04 3.17.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618902/86971f52-0e42-330b-10e9-2fe1dab1b1b3.png">

ではどうすればいいのでしょうか。
以下のように**userとcourseの中間にデータの橋渡しをしてあげる中間テーブルを作成**します。
そうすることでキレイなDB設計が可能となり、userやcourseが増えたとしても中間テーブルにデータを追加するだけでOKなのです。
<img width="599" alt="スクリーンショット 2020-06-04 3.22.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618902/2d9f9fd2-2544-bef5-2e34-5b79605f4258.png">

##参考サイト
[1.やさしい図解で学ぶ　中間テーブル　多対多　概念編](https://qiita.com/ramuneru/items/db43589551dd0c00fef9)
[2.若手プログラマー必読！５分で理解できるER図の書き方５ステップ](https://it-koala.com/entity-relationship-diagram-1897#ER-4)
Call to undefined method Illuminate\Database\Eloquent\Builder::toArray() の解決例

#エラー文の様子
<img width="1199" alt="スクリーンショット 2020-06-04 2.43.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555157/49335628-7f02-ee66-69d4-d0543bb4fae8.png">

#どんなエラー？

```php:app/Http/Controllers/RecordTimingController
public function syousai_matome($id)
     {
       $third_operation_class_id = Operation::query()->where('record_timing_id',$id)->distinct()->select('third_operation_class');
       return $third_operation_class_id->toArray();
      }
```

上記のように、コントローラで構文的に問題なくデータベースから情報を取得しようとしたら出てきたものです。

#原因

データベースの情報をクエリ（今回は抽出）した状態で止まっており、その抽出したものをコントローラに呼び出していなかったため起きました。

※クエリとは：**データベース上で**特定の条件に合致したデータを検索したり、置換や削除などを行ったりすること。

#解決策

下記のように、クエリ（今回は抽出）した状態のものを`->get()`で取得すればエラーが解消されました。

```php:app/Http/Controllers/RecordTimingController
public function syousai_matome($id)
     {
       $third_operation_class_id = Operation::query()->where('record_timing_id',$id)->distinct()->select('third_operation_class')->get();
       return $third_operation_class_id->toArray();
      }
```
IFTTT使って、Google HOMEからLineに音声入力してみた。

# はじめに

Google Home に「おやすみ」しかいってない現状なので、
そろそろGoogle Homeさんに嫌われそう。

なんかと連携したいなーって思って、まっ先にLine連携を思いつく。
たまに打ち過ぎて指痛くなるのでちょうど良さそう。





# ざっくり構成図

絵にするまでもない。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/a28e8208-75a0-6740-0cea-b140638ada21.png)






# 今さらIFTTT

遅ればせながら[IFTTT](https://ifttt.com/my_applets)触ってみる。

> にしても、IFTTTTって名前、とてもシンプルｗｗ



とりま、IFTTTにログインして"Line"で検索。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/8c61d04b-0a42-cebe-1206-7e6c3200f6fb.png)


めちゃ出る！そしてあった！笑（ここまで2分）

![3-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/757a91c9-8950-6fca-2086-92c127477b68.png)



流れに沿ってポチる。
けど、なんかログインできない…。なんでーー！！！（10分くらい？）



どうやら、IFTTTTと連携されてないから、みたい。なるほど。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/e44a7921-a791-3d47-7821-58f4f96e8f73.png)



同意して連携してみる。できた。（ここで11分）

その後にLine notifyと友達になる。こいつが通知してくれる。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/db2e3095-c775-e107-dad3-1f12e6cc7a53.png)

ただし、グループにしか設定はできない様子。（グループじゃないしゃべり場は無理。）
グループにLine notifyを招待する。（ここまで13分）



**はい、終わり！**



# 実際にやってみた

さすが、我が家のGoogle Homeさん。
ちゃんと拾ってくれる。

最後の「～を送って」は言わなくても良い様子。

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384185/f3e17b1a-69c8-0c14-2371-c4c279f75d63.png)


# おわりに

すごい簡単なのに、してやった感がすごい。
コーディングとかしないでこんな短時間で連携できちゃうのか。。。

IFTTTを真面目に使ってみよう。
PRML 演習問題 3.4　解答

## 問題
> 次の形の線形モデル
$$
\begin{align*}
\{y} (\mathbf{x}, \mathbf{w})=w_{0}+\sum_{i=1}^{D} w_{i} x_{i}
\tag{3.105}
\end{align*}
$$
と二乗和誤差関数

```math
\begin{align}
E_{D}(\mathbf{w})=\frac{1}{2} \sum_{n=1}^{N}\left\{y\left(\mathbf{x}_{n}, \mathbf{w}\right)-t_{n}\right\}^{2}
\tag{3.106}
\end{align}
```


を考える。
平均 $0$、分散 $\sigma^{2}$のガウスノイズ $\epsilon_{i}$ が独立にそれぞれの入力変数 $x_{i}$に加わるものとする。$\mathbb{E} [\epsilon_{i}]$ = $0$ と $\mathbb{E} [\epsilon_{i}\epsilon_{j}]$ = $\delta_{i j}\sigma^{2}$ の2つの性質を用いて、$E_{D}$のノイズ分布に関する平均を最小にすることは、ノイズのない入力変数に対する二乗和誤差関数と荷重元帥の正則化項の和を最小にすることと等価であることを示せ。ただし、正則化項にバイアスパラメータ $\omega_{0}$ は含めない。


## 解答
ノイズが加わった入力 $x$ を、

```math
\begin{align}
\tilde{x}_{n i}=x_{n i}+\epsilon_{n i}
\end{align}
```

とすると、対応する出力 $y$ は

```math
\begin{align}
\tilde{y}_{n}=y\left(\tilde{x}_{n}, w\right)=w_{0}+\sum_{k=1}^{D} w_{i} \tilde{x}_{n i}=w_{0}+\sum_{k=1}^{D}\left(x_{n i} +\epsilon_{n i} \right)=y_{n}+\sum_{i=1}^{D} w_{i} \epsilon_{n i}
\end{align}
```

となる。
ノイズが加わった状態での二乗和誤差を $\tilde{E}$ とすると、

```math
\begin{align}
\tilde{E} &=\frac{1}{2} \sum_{n=1}^{N}\left(\tilde{y}_{n}-t_{n}\right)^{2}=\frac{1}{2} \sum_{i=1}^{N}\left(\tilde{y}_{n}^{2}-2 \tilde{y}_{n} t_{n}+t_{n}^{2}\right) \\
&=\frac{1}{2} \sum_{n=1}^{N}\left(y_{n}^{2}+2 y_{n} \sum_{n=1}^{D} w_{i} \epsilon_{n i}+\left(\sum_{i=1}^{D} w_{i} \epsilon_{n i}\right)^{2}-2 y_{n} t_{n}-2\left(\sum_{i=1}^{D} w_{i} \epsilon_{n i}\right) t_{n}+t_{n}^{2}\right)
\end{align}
```

問題文より、$\mathbb{E}[\epsilon_{i}]$ = $0$ なので、上式の第２項と第５項は $\epsilon_{i}$ についての期待値をとると０となる。第３項について、誤差に関して期待値をとると、

```math
\begin{align*}
\mathbb{E}_{\epsilon}\left[\frac{1}{2} \sum_{n=1}^{N}\left(\sum_{k=1}^{D} w_{i} \epsilon_{n i}\right)^{2}\right] \
& = \frac{1}{2} \sum_{n=1}^{N} E_{\epsilon}\left[\left(\sum_{x=1}^{D} w_{i} \epsilon_{n i})^{2}\right]\right. \\
& =\frac{1}{2} \sum_{k=1}^{N} \mathbb{E}_{\epsilon}\left[\left(w_{1} \epsilon_{n_{1}}+\cdots+w_{D} \epsilon_{n_{D}}\right)^{2}\right] \\
& =\frac{1}{2} \sum_{n=1}^{N} \mathbb{E}_{\epsilon}\left[\left(w_{1}^{2} \epsilon_{n 1}^{2}+\cdots +w_{D}^{2} \epsilon_{n D}^{2}\right)\right. + 2\left(w_{1} w_{2} \epsilon_{n 1} \epsilon_{n 2}+\cdots+w_{D-1} w_{D}\epsilon_{n D-1} \epsilon_{n D})\right] \\
& = \frac{1}{2}\sum_{n=1}^{N}\mathbb{E}_{\epsilon}\left[w_{1}^{2} \epsilon_{n 1}^{2}+\cdots+w_{D}^{2} \epsilon_{n D}^{2}\right]+2E_{\epsilon}\left[w_{1} w_{2} \epsilon_{n 1} \epsilon_{n 2}+\cdots+w_{D-1} w_{D}\left(\epsilon_{n D-1} \epsilon_{n D}\right]\right. \\
& =\frac{1}{2} \sum_{n=1}^{N}\left[\mathbb{E}_{\epsilon}\left[\sum_{i=1}^{D} w_{i}^{2} \epsilon_{n i}^{2}\right] 
= \frac{1}{2} \sum_{n=1}^{N} \sum_{i=1}^{D} w_{i}^{2} \sigma^{2}
=\frac{N \sigma^{2}}{2} \sum_{i=1}^{n} w_{i}^{2}\right.
\end{align*}
```

よって、

```math
\begin{align*}
\mathbb{E}_{\epsilon}[\tilde{E}] \
& =E_{\epsilon}\left[\frac{1}{2} \sum_{i=1}^{N}\left(y_{n}^{2}-2 y_{n} t_{n}+t_{n}^{2}\right)\right]+\frac{N\sigma^{2}}{2} \sum_{i=1}^{D} w_{i}^{2} \\
& =\frac{1}{2} \sum_{n=1}^{N}\left(t_{n}-y_{n}\right)^{2}+\frac{N\sigma^{2}}{2} \sum_{i=1}^{n} w_{i}^{2} \\
& =E_{D}(\mathbf{w})+\frac{n\sigma^{2}}{2} \mathbf{w}^{\top} \mathbf{w}
\end{align*}
```

よって、題意は示された。