OmniAICreator/Qiita-1.07M huggingface dataset:
Build input file cannot be found: xxx Info.plistとなった時の対処法

Info.plistのディレクトリを変更した際に上記のエラーが起きました。
今までなら`General => Choose info.plist file`でpathを指定できたのですが、見つからなかったので書きました。

## 対処法
- **Project => Build Settings => Info.plist File**

info.plistファイルまでのパスが変更前の`{プロジェクト名}/Info.plist`になっているはずですので、
変更後のパスに修正します。

![スクリーンショット 2020-09-07 0.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/6a7506e8-6fda-31a7-e9bc-0c14186346e6.png)

ディレクトリからD&Dで移せばパスがそのまま取れるので便利です。(※/User/あたりは削除)


## 参考
- [xcode10 - 'Build input file cannot be found' Swift 4.2, Xcode 10.0 - Stack Overflow](https://stackoverflow.com/questions/52435202/build-input-file-cannot-be-found-swift-4-2-xcode-10-0)[xcode10 - 'Build input file cannot be found' Swift 4.2, Xcode 10.0 - Stack Overflow](https://stackoverflow.com/questions/52435202/build-input-file-cannot-be-found-swift-4-2-xcode-10-0)
javascriptのfor文について

javascriptを触ってて
for文周りって色々あるけどfor以外使ったことなかったので調べてみました。

---

## for
まずはスタンダード？なfor文から。

---

```js

const arr = ["banana", "apple", "orange"];
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}
```

---

出力結果としては

```
banana
apple
orange
```
となります。

---

for(初期値; 条件式; 増減値) {}
のように3つの引数を入れてあげれば出力できました。

自分はよくこれを使っています。

---

## for-in
次はfor-inで、これはあまり使ったことがないのですがオブジェクトの中身などを取り出したいときに使用されるみたいです。

---

```js
const obj = {
  name: "太郎",
  age: 15
}

for(let key in obj) {
  console.log(key + ":" + obj[key]);
}
```

---

出力結果としては

```
name: 太郎
age: 15
```
となります。

---

for (変数 in オブジェクト)とすれば
オブジェクトのプロパティの数だけ繰り返してくれます。

---

## for-of
for-ofは配列に対して使用できます。

---

```js
const items = [1,2,3,4,5,6];

for (let item of items) {
  console.log(item);
}
```

---

出力結果としては

```
1
2
3
4
5
6
``` 
となります。

---

for (変数 of 配列)とすれば配列の数だけ繰り返します。
for文のように条件式を入れないのでこっちの方がわかりやすい印象です。

---

## foreach
最後はforeachですがこれは配列に対してつかえます。

---

```js

var items = [
  {
    id: 1,
    name: "太郎"
  },
  {
    id: 2,
    name: "健"
  }
];
 
items.forEach( function( value ) {
    console.log( value.name );
});
```

---

配列の要素一つ一つに対して処理を実行できるので使いどころが多そうな印象です。

---

## まとめ

---

今回はjavascriptのfor系を調べてみました。
同じようなものでも違いがあるので色々調べてみて使ってみたいと思います。
【Rails】rakeタスクを実装する

## rakeタスクとは
ファイルに記述した処理をコマンドラインから実行する機能です。
ユーザーの属性に応じてステータスを変更する、CSVデータをインポートする、任意のタイミングでユーザーにメールを送る、などなど様々な用途で使われます。

## 基本的な使い方
### タスクファイルを生成
```zsh
$ rails g task qiita_task
```
### 実行したい処理を記述
```rb
namespace :qiita_task do
  desc 'hello worldします'
  task :hw do
    puts 'Hello World'
  end
end
```
### 実行
```zsh
$ rake qiita_task:hw
```
## その他
### タスクの中にDBに接続する処理が含まれる場合
DBに接続する場合、以下のように`environment`と記述する

```rb
namespace :qiita_task do
  desc '最近登録したユーザーにメールを送信'
  task send_email_to_recent_users: :environment do
    recent_users = User.where('updated_at <= ?', Time.zone.parse('2020/09/08 15:50:00'))
    recent_users.each do |ru|
      ru.send_email
    end
  end   
end
```

### 本番環境で実行する
プロジェクトのルートディレクトリ(Gemfileとかがあるとこ)で、`RAILS_ENV=production`をつけて実行。

```zsh
$ rake qiita_task:hw RAILS_ENV=production
```

### タスク一覧を表示
デフォルトで定義されているタスクと、自分が作成したタスクがずらっと表示されます。

```zsh
$ rake -T
```

## 参考
- [RailsでRakeタスクの作成 - Qiita](https://qiita.com/suzuki-koya/items/787b5562d2ae1a215d94)
(JS)絶対にDeep Mergeを自力で実装しないでください

# tl;dr

- JavaScriptでオブジェクトのdeep mergeをしたいならこの記事を読むか、あるいは最新版のlodashを使ってください
- 自力で実装したdeep mergeを使う場合は、引数にユーザーの入力(JSONなど)を使わないでください

# deep merge? なにそれ
オブジェクトの引数を再帰的に設定する関数で、lodashでいえば[merge関数](https://lodash.com/docs/#merge)とかに相当。

# プロトタイプ汚染の闇
JavaScriptのオブジェクトには99%プロトタイプが存在します。偉い人はオブジェクトを`Object.create(null)`で作ったりしますが、そういう人は稀です。

プロトタイプの属性は、同名の属性が元のオブジェクトに存在しない場合のフォールバックとして使われます。たとえば、いつも使う`hasOwnProperty`は、実は`Object`のプロトタイプ内に存在するのです。

では、そのプロトタイプを書き換えられたらどうでしょうか。たとえば、`hasOwnProperty`が`1`になったら、`({}).hasOwnProperty("foo")`といったコードがエラーを出します。もし認証系のコードで「isAdmin属性が存在すれば管理者だ」を`const isAdmin = ({}).isAdmin;`のように実装していれば、立派な権限昇格です。これは「プロトタイプ汚染」(Prototype Pollution)と呼ばれます。

そして、プロトタイプ汚染が怖いのは、deep mergeという簡単な操作で、引き起こせるからです。

# Deep Merge クイックテスト
もし下のオブジェクトを空のオブジェクトにdeep mergeして、`Object.prototype.isAdmin`がセットされたら、プロトタイプ汚染成功です。(自分のコードでのみ試してください... 本番環境のAPIに投げるのはお勧めしません。)

```json
{
  "__proto__": {"isAdmin": 1},
  "constructor": {"prototype": {"isAdmin": 1}}
}
```

# 安全なdeep merge
一番安全なのは、lodashのようなライブラリーを使うことです。なお、最新版を使うことをお勧めします。

それでも自力で実装したい場合は

- `__proto__`、`constructor`、`prototype`のキーが出てきたら無視する。
- merge先の`hasOwnProperty`の結果がfalseの場合は、空のオブジェクトを作成する。(`typeof merge先 === "object"`のみだと不十分。)

のような安全策を取らないといけません。荒技としては`Object.freeze(Object.prototype)`で汚染をできないようにすることもできますが、あくまで荒技です。
[解答]rails にカート機能を追加する-モデル部分

購買者購入履歴のためのモデルを作る

```terminal:ターミナル
$ rails g model UserProduct
```
モデルとマイグレーションファイルができたと思うので、マイグレーションファイルを編集する

```ruby:db/migrate/20190831095111_create_tags.rb
class CreateUserProducts < ActiveRecord::Migration[5.2]
  def change
    create_table :user_products do |t|
      t.integer :user_id #購入者
      t.integer :product_id #商品
      t.integer :lot #買った個数
      t.timestamps
    end
  end
end
```
編集し終えたら、データベースを更新するためにマイグレーションをかける

```terminal:ターミナル
$ rails g db:migrate
```

購買者購入履歴の関係をmodelで定義する。
・あるユーザーは多くの購買者購入履歴(買った商品)を持っている
・ある商品は多くの購買者購入履歴(買ったユーザー)を持っているので
多対多の関係

```ruby:app/model/user.rb
class User < ApplicationRecord
	devise :database_authenticatable, :registerable, :recoverable,
	 :rememberable, :trackable, :validatable, :confirmable
	has_many :products
	has_many :user_products
end
```
```ruby:app/model/product.rb
class Product < ApplicationRecord
	belongs_to :user
	has_many :user_products
end
```
```ruby:app/model/user_product.rb
class UserProduct < ApplicationRecord
	belongs_to :user
	belongs_to :product
end
```
lessコマンド でファイル書き換えてみる

## lessコマンド でファイル書き換えてみる

### lessコマンドとは？

テキストファイルを1画面ずつ表示するコマンド
`less /var/log/messages` で、messagesのログファイルを確認することができます。
大体、確認する際に`less`を使うことが多いかと思います。


### lessコマンドでファイルの書き換えをしてみる

- サンプルファイルの準備

```
$ echo aaaaaaa > sample.txt
$ cat sample.txt 
aaaaaaa
```

- サンプルファイルの書き換え

```
less sample.txt 
==========
aaaaaaa
==========
```
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/6fbdef64-39a0-ebc2-4997-35e7a0e3a13b.png)


↑の `less` を開いた状態で `v` を押すと↓のように変換モードになる

```
aaaaaaa
```
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/aaf8ac83-776a-b569-ad6a-a5c33b7b5d89.png)


`test` という文字列を追加

```
aaaaaaa
test
```
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/0f2724ea-5f79-5e1e-eeff-b7e75f5e0d78.png)


`:wq` で保存

```
aaaaaaa
test
```
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/03f7a00e-9a4e-6228-4193-279e23633b6b.png)

`less` の状態で戻るので、閉じます。

確認すると変更されている

```
$ cat sample.txt 
==========
aaaaaaa
test
==========
```

### 対応策

重要なファイルをタイポで書き換えてしまう可能性があります。
書き換えれないように、 以下のようにcatコマンドを使用することで防ぐことができます。

```
cat sample.txt | less
```
ちなみに、↑のコマンドで `v` を押すと、以下のように編集できない旨表示されます。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/faf9dc29-5ed4-01f5-2361-59b411972d63.png)
bin/cake bake migration_snapshot Initialをするときにはtinyintに注意する

# やりたこと
[こちら](https://qiita.com/learn_tech1/items/bfec6be5d64affc74c07)のコマンドで、既存のDBからMigrationファイルを生成すると、booleanとして扱いたいtinyintのカラムがtinyintegerとしてMigrationファイルを生成してしまう。
tinyintはbooleanに変換したい。

# 環境(今回の作業に関連ないものも記載)
* cakephp4.1.2

# 実装
[こちら](https://qiita.com/learn_tech1/items/e348bf3c32391c3d6be8)をベースに、sedを追加した。
データベースをtinyint(1)とかにしてもtinyintegerのままだったので、ファイル生成した後に置換することで対応した。

```
rm -f ./config/Migrations/*_Initial.php
bin/cake bake migration_snapshot Initial
sed -i -e 's/tinyinteger/boolean/g' ./config/Migrations/*_Initial.php
bin/cake migrations rollback -d 20200101
bin/cake migrations migrate
bin/cake migrations seed --seed LocalSeed
bin/cake bake baked_model all -f
bin/cake bake extended_model all -f

```
convertコマンドでエラー

# 概要
最近はスマホの画質もよくなってきて画像のファイルサイズもだいぶ大きくなってきましたよね。。。
特にiPhoneだとなぜか拡張子がheicファイルとなっててブログに記事を書くときとかjpgにしたかったりします。
そんな時に写真が大量にあるならImageMagickで変換したくなります。
convertコマンドを実行したら下記のエラーが。


```
convert-im6.q16: cache resources exhausted
```
このエラーはどうやらメモリ不足が原因のようなので、
メモリをあげます。
下記のファイルを開きます。
/etc/ImageMagick-6/policy.xml

メモリの記述のある下記を適当な値に変更します。

```
<policy domain="resource" name="memory" value="256MiB"/>
```
ここvalue値を4GiBなど適当な値に変更します。
デプロイコマンドを実行する際に対話形式で確認

デプロイのコマンドを実行する際に、処理継続の確認をするためのスクリプトを書きます。
指定された入力があれば、そのあとの処理を続けて実行、指定と違えばそこで終了します。

# 作成

```shell:confirm.sh
#!/bin/bash

LAST_STAND=$1

function Confirm() {
    QUESTION=$1
    ANSWER=$2
    NOTE=$3
    ANOTATION=$4
    read -p $'\033[0;34m?\033[0;39m'" ${QUESTION}: "$'\033[1;30m('"${NOTE}"$')\033[0;39m ' INPUT

    if [ -z "${INPUT}" ] || [ "${INPUT}" != "${ANSWER}" ]; then
        echo "\n\033[0;31m${ANOTATION:-スクリプトを終了します。}\033[0;39m"
        exit 1
    fi
}

Confirm "処理を続行する場合は「${LAST_STAND}」と入力してください。" "${LAST_STAND}" "${LAST_STAND}"

echo "\n\033[0;32mスクリプトを実行します。\033[0;39m"
```

# 設定

```json:package.json
{
  "scripts": {
    "predeploy": "sh confirm.sh DEPLOY"
    "deploy": "echo deploy"
  }
}
```

# 実行

```shell
$ npm run deploy
```
【IOU】 Object Detection の性能指標【I/U】


ユニオン交差 Intersection Over Union (IOU) が一般的なようです。
![iou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/edde1efc-834f-c528-8d71-202ac6106399.png)

**IOU = 正解boxと予測boxの重なりあう領域　／　正解boxと予測boxの重なり合っている部分と重なり合っていない部分の和**

つまり、IOUが100%であれば、完璧に正解と予測が一致しているということです。

CreateMLの正解率は、このIOUが５０％を越えているもの（５０％重なっているもの）を正解とみなして％表示しています。


I/U 50%
87%

というのは５０％領域が重なっているケースが８７％あったということです。

もう一つの指標、varied I/Uというのは、閾値を５０％〜９５％まで変化させた時の平均正解率。
これが低いと、重なっている部分はあるものの、重なる領域は狭い、ということになります（もちろん５０％閾値の正解率以下になります）。

****
Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[MLBoysチャンネル]
(https://www.youtube.com/channel/UCbHff-wfjTnB3rtXIP6y0xg)
[Medium](https://medium.com/@rockyshikoku)

[相棒](https://twitter.com/oka_yuuji)
[note](https://note.com/oka_yuuji)
【練習】列挙　

列挙の練習

◎rekkyo練習クラス

```JAVA
package rekkyo_renshu;

public class Film {
	private String Name;		// 予約名
	private FilmType filmType;	// 映画のなまえ

	// 列挙型の宣言。これ以外を指定してインスタンスは作れない
	enum FilmType{
		COMEDY,LOVE,HORROR
	}

	public Film(String name,FilmType ft) {
 //受け取ったnameをそのまま使う（switch文では特に使用しないので） 
 //ここに代入
		String Name=name; 
        
//switch文で、各列挙型の変数入りインスタンスが生成された時の処理
		switch(ft) {
		case COMEDY:
			filmType=FilmType.COMEDY;
			System.out.println("予約映画名[AustinPowers] 予約者名["+Name+"]");
			break;

		case LOVE:
			filmType=FilmType.LOVE;
			System.out.println("予約映画名[AboutTime] 予約者名["+Name+"]");
			break;

		case HORROR:
			filmType=FilmType.HORROR;
			System.out.println("予約映画名[Shining] 予約者名["+Name+"]");
			break;

		}

	}

}

```

◎Mainクラス

```java

package rekkyo_renshu;

import rekkyo_renshu.Film.FilmType;

public class Main {

	public static void main(String[] args) {
		Film film1=new Film("ヤマダタカユキ",FilmType.COMEDY);

	}
}


```

実行結果

予約映画名[AustinPowers] 予約者名[ヤマダタカユキ]
nuxt generateする際のGTM設定方法

nuxt generateすると1ページ目しかPV計測ができなかった。

generate時のPV計測は設定が必要なそうな。
ググった感じ、どうやらいろいろと方法があるみたい。
今回はGTM側でカスタムイベントを使う方法を採用。

インストールなどは公式を参考。
https://github.com/nuxt-community/gtm-module

#nuxt.config
pageTracking: trueがキモ。
PV発生時にカスタムイベントの重複を防ぐため、pageViewEventNameを設定しておいた。

```nuxt.config.js
export default {
  modules: [
    '@nuxtjs/gtm',
  ],
  gtm: {
    id: 'GTM-XXXXXXX',
    pageTracking: true,
    pageViewEventName: 'カスタムイベント名',
  }
}

```

#GTM
タグは普通にGAの設定をしておく。

##トリガー
トリガータイプ：カスタムイベント
イベント名：カスタムイベント名




でプレビューを確認しよう！
ページ遷移のたびSummaryにカスタムイベント名が追加されていれば、GAでもリアルタイムでPVとれてるはず。
commit failed exit code 1のエラー解決方法

【概要】
----------------------------------------
<b>1.結論</b>

<b>2.なぜ"commit failed exit code 1"になるのか</b>

<b>3.どのように解決するか</b>

<b>4.ここから学んだこと</b>


1.結論
----------------------------------------
git cloneしたファイルを削除する。

<br>
2.なぜ"commit failed exit code 1"になるのか
----------------------------------------
![スクリーンショット 2020-09-09 15.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686400/271d8699-79b1-ea62-fd07-24bcd87628e9.png)

以前に

```terminal:ターミナル
% git clone https://github.com/"githubのアカウント名"/"githubのリモートレポジトリファイル名”.git
```
行ったことが原因でした。
上記のようにgitcloneしたものがcommitしたいファイルに残っていたせいでした。

<br>
3.どのように解決するか
----------------------------------------
該当ファイルの中の場所に"clone_site"と作ってありました。そのファイルを削除して、再度新たにgithubに反映させたいファイルを指定してcommitするとエラーは解消しました。
<br>

4.ここから学んだこと
----------------------------------------
当時git cloneした際は一瞬だけ少し試したいことがあったため使用しました。なので、用済みであればそのファイルは消すか、commitしない自信がそのファイルは使用しない方向にするべきでした。そうしないと、今回のようにgit cloneしたことを忘れかけていたので土壺にはまり時間をうばわれかねません。
<br>
単体テストフレームワークのassertEqualsの想定値は1番目なのか2番目なのかまとめ

想定値を示す引数 `expected` は引数の1番目なのか、2番目なのか、まとめます。ふだんはJUnit/XCTest/PHPUnitあたりを主に使って仕事してますので、それ以外の言語はもしかしたら普通は使用しないようなフレームワークについて書いてるかもしれません...。
また、xUnit系のテスティングフレームワークだけ挙げてます。xSpec系のテスティングフレームワークは、自分はほぼつかったことないのですが、大体 `expect(テスト結果).to eq 想定値` となっていそうでした。
まず調べた結果の表です。

| フレームワーク | 1番目 | 2番目 | 3番目 | 備考(言語など) |
|:----------:|:----:|:----:|:----:|:----|
| JUnit | (message) | <font color="Red">expected</font> | actual | Java, Kotlin, ... |
| XCTest | actual | <font color="Red">expected</font> | (message) | Swift |
| PHPUnit | <font color="Red">expected</font> | actual | (message) | php |
| chai | actual | <font color="Red">expected</font> | (message) | JavaScript. アサーションライブラリです |
| Test::Unit | <font color="Red">expected</font> | actual | (message) | Ruby |
| unittest | actual | <font color="Red">expected</font> | (message) | Python |

`expected = 想定値 / actual = テスト結果の値 / message = 失敗時メッセージ`
`message`はオプションであることを示すために`()`で囲っています。
JUnitは2番目になってますが、messageはオプションなので、実質1番目でしょうか...。
そうすると、ここに挙げたものだけをみる限りですが...ちょうど割れてる感じです😅

## JUnit
### Java, Kotlin など
1番目 (失敗時メッセージがある場合は2番目)

```java
assertEquals(message, expected, actual);
```
https://github.com/junit-team/junit4/wiki/Assertions
※ JUnit4
## XCTest
### Swift
2番目 (失敗時メッセージは最後)

```swift
XCTAssertEqual(view.frame.size, expectedSize, "Unexpected frame size.")
```
引数名は、`expression1`と`expression2`になっていて一見どっちかわからないけど、サンプルを見ると2番目に想定値をいれるのが一般的っぽい。
https://developer.apple.com/documentation/xctest/2142776-xctassertequal
## PHPUnit
### PHP
1番目 (失敗時メッセージは最後)

```php:php
assertEquals($expected, $actual, $message);
```
https://phpunit.readthedocs.io/ja/latest/assertions.html#assertequals

## chai
### JavaScript
2番目

```javascript
assert.strictEqual(actual, expected, message);
```
アサーションライブラリです。使ったことないですが、[Mocha](https://mochajs.org/)というテスティングフレームワークと組み合わせて使用することが多そうです。
https://www.chaijs.com/api/assert/

## Test::Unit
### Ruby
1番目

```ruby
assert_equal expected, actual, message
```

https://docs.ruby-lang.org/ja/2.1.0/class/Test=3a=3aUnit=3a=3aAssertions.html

## unittest
### Python
2番目 (失敗時メッセージは最後)

```python
assertEqual(first, second, msg)
```
引数名は、`first`と`second`になっていて一見どっちかわからないけど、サンプルを見ると2番目に想定値をいれるのが一般的っぽい。
https://docs.python.org/ja/3/library/unittest.html#unittest.TestCase.assertEqual

## flutter_test
### Dart
2番目

```dart
expect(actual, matcher, reason: reason);
```
（`expect()` なので...ここに挙げるか迷いましたが...最近よく使ってるので）
https://api.flutter.dev/flutter/flutter_test/expect.html
さくらのクラウドのサーバーインスタンスにNICを追加してローカルIPを割当てる OSはUbuntu18

# さくらのクラウドにサーバーを作って NIC 追加してローカルIPを割当てる

## こんな構成にしたいとき
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6384/b927f47a-2c13-ba2f-bcf0-3039d34bf21f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6384/a68a81a5-b8c5-0991-e6b3-95732ce28f45.png)

インターネットにつなげるサーバーと
インターネットにつなげないサーバーを分ける。
インターネットにつなげるとどんな攻撃が来るかわからない。だから大切なデータが入っているサーバーをインターネットに直接繋がない様にしたい場合。

## インターネットにつなげる サーバーA には NICが２つ必要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6384/5a1f5a20-f624-03f2-96c9-7275d41db9d2.png)
NICとはネットワーク インターフェース カード
NIC1はインターフェースにつなげて
NIC2はLANにつなげる

## 実際の構成
![さくらのクラウドにNICを追加してローカルIPを割当てる OSはUbuntu18b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6384/b1ed6a09-d747-b2c1-5024-89f542a2ee0d.png)

サーバーを作成。作成時にNICにグローバルIPを割り当て。サーバーインスタンス作成後にNICを追加してスイッチに接続。スイッチのアドレスは192.168.101.1でVPNルーターを設定済み。そとからMacBook ProなどでVPN接続して、Ubuntuサーバーにログインしたりする。

今回は NICを追加して ローカルIPアドレス 192.168.101.20 を設定する手順を記録。

### 設定手順 eth1デバイスが作成されていることを確認
コマンドを実行。
ip addr
を実行してアドレス割当状態を確認

ipconfig -a 
で、eth1デバイスが存在することを確認する。

### netplan
Ubuntu18から netplan とか言うものでネットワーク設定を行っているらしい。詳細は下記参照。
https://wiki.ubuntu.com/Netplan
https://netplan.io/


### バックアップをとる
sudo cp -p /etc/netplan/01-netcfg.yaml /home/ubuntu/01-netcfg.yaml.bkup

ネットワーク設定間違えるとSSHでログインできなくなります。もとに戻せるようにバックアップをとっておきましょう。ん？SSHログインできなくなったときにどうやって設定を戻すの？
そのときはさくらのクラウドのコンソールを使って作業しましょう。
https://manual.sakura.ad.jp/cloud/server/console.html


### 01-netcfg.yaml を編集

sudo vi /etc/netplan/01-netcfg.yaml
を実行してviエディタで編集。nanoエディタでもOK。

変更後の01-netcfg.yaml

```yaml
network: 
  ethernets: 
    eth0: 
      addresses: 
        - 153.125.512.30/24
      dhcp4: 'no'
      dhcp6: 'no'
      gateway4: 153.125.512.1
      nameservers: 
        addresses: 
          - 133.242.0.3
          - 133.242.0.4
        search: 
          - localdomain
    eth1:
      addresses:
        - 192.168.101.20/24

  renderer: networkd
  version: 2

```


以下の部分が追記する部分。
* eth1: などのデバイス名が ifconfig -a の名前と同じかどうかを確認する。

```yaml
    eth1:
      addresses:
        - 192.168.101.20/24
```

### 設定を反映
sudo netplan apply
を実行してifconfigでアドレスが反映されているかを確認。

### 再起動してみる
sudo shutdown -r now
で再起動して、SSHでログインしてifconfig でネットワーク設定が有効になっていることを確認。
このとき設定を間違えているとSSHでログイン出来なくなっているかも。そのときはコンソールを使って設定を戻しましょう。


今回netplanを初めて知った。詳しくないので間違ってるかも。
マサカリ歓迎でーす。
Python3.6のパッケージングとモジュールについて



パッケージ? モジュール？を作る必要があったが、Pythonの基本がわからずハマってしまったので備忘録として残しまます。

ひとまずパッケージとモジュールの違いがわからないが、実験から以下を得られた.


### 環境

- Python3.6



### 条件

ディレクトリ構成

```
fisig/
  __init__.py    # 空のファイル
  converter/
    __init__.py
    base.py
    sound.py
    acc.py
```




sound.py

```py

from .base import base_converter
class SoundConverter:
    def convert():
        base_converter()

```


importのパターン

```py


def test_import():
    import abesig.converter
    abesig.converter.sound.SoundConverter()

    import abesig.converter.sound
    abesig.converter.sound.SoundConverter()

def test_NG():
    with pytest.raises(ModuleNotFoundError):
        import abesig.converter.sound.SoundConverter

def test_from_import():
    from abesig import converter
    converter.sound.SoundConverter()

    from abesig.converter import sound
    sound.SoundConverter()

    from abesig.converter.sound import SoundConverter
    SoundConverter()


```

つまり、以下のようにはできない。言われてみると経験からわかるが。パイソニックには説明ができない。。まだまだ未熟でした。

```py

import abesig.converter.sound.SoundConver
SoundConver()
```



## その2: エイリアスを使う場合

(パイソニスタはエイリアスをなんというのだろう)


fisig/converter/__init__.py


```py
from .sound import SoundConverter
```

test_import.py


```py

def test_ailias():
    import abesig.converter
    abesig.converter.SoundConverter()

    from abesig import converter
    converter.SoundConverter()

    from abesig.converter import SoundConverter
    SoundConverter()
```


## 余談

下の記事を読んで用語を整理

[Python の __init__.py とは何なのか - Qiita](https://qiita.com/msi/items/d91ea3900373ff8b09d7)
[Python 3.3b1 の名前空間パッケージを試してみた — 清水川Web](http://www.freia.jp/taka/blog/hello-python-3.3b1/index.html)


- モジュール = `xxxx.py 1ファイル`のこと. 
- パッケージ = 複数ファイルをまとめたもの
- 名前空間 = 名前空間
- from/import = あくまでも`モジュール`のインポート
    - つまりfrom --- import --- の`末尾`はモジュールをさす
    - モジュール(xxx.py)内のクラス/メソッドを使いたい時に使う
- パッケージ < モジュール < クラス/メソッド
FLASKでクイズアプリをつくる

<h1>やりたいこと</h1>

エクセルファイルからクイズデータを読みこみ、クイズを出題する。
答えの選択肢が３つあれば、３択クイズ。ひとつだけなら入力問題にする。

<h3>工夫するとこ</h3>

■クイズのテーマを選ぶことができる
■問題はランダムにでてくる
■３択の順番も変わる

<h3>方法</h3>
  
<code>python-3.8.5 
Flask</code>
エクセルファイルを読みこみ、出題する

<h3>今後の計画</h3>
クイズデータをデータベース上におき、第三者も登録できるようにする
正解率をデータベースに記録し、年齢ごとにちょうど良い難度（８０％くらいかな）の問題を出題する

<h3>コード</h3>
<link>https://github.com/isamimasi/quiz</link>
<h3>Demo</h3>
<link>http://isamimasiquiz.herokuapp.com/</link>
OpenAPI3へのスキーマファースト開発移行(ツール編)

# OpenAPI3へのスキーマファースト開発移行(ツール編)
スキーマファースト開発をプロジェクトへ導入してから1年が経ちました。
ツール編では移行の方針や使用ツールについて書いていきます。

## Prerequisite :runner:
* Rails + vue.jsのSPA開発
* TDD導入済み

## Tools :wrench: 
* [OpenAPI3](#openapi3)
* [Swagger Editor](#swagger-editor)
* [multi-file-swagger](#multi-file-swagger)
* [OpenAPI Generator](#openapi-generator)
* [committee](#committee)

## Why :question:  
* SPA開発においてAPIとクライアントの開発を行っていましたがチーム開発においてAPI実装への依存度が高かった
* チームメンバーが増えてくるとAPI仕様の共有や変更の共有にコミュニケーションコストが増えてきた
* API仕様書を正にして変更があれば自動テストをFailさせたい

## Purpose and Rules :triangular_ruler:
* API・クライアントの実装効率化
* RESTful API準拠及びOpenAPI3に仕様準拠
* YAMLで管理
* API仕様書の分割と結合
* YAMLのAPI仕様書を読み込み自動テスト(API/クライアント)
* API仕様書からhtmlドキュメントを生成
* (モックサーバー起動)

## Tools詳細
### OpenAPI3
* [OpenAPI3](https://swagger.io/specification/)
* REST-APIの標準仕様であり3系から効率的に記述できるようになっているため3系を使用します
* [docs](https://swagger.io/docs/specification/about/)
* ドキュメントは英語のみですがサンプルも多く十分理解しやすいです


### Swagger Editor
* [Swagger Editor](http://editor.swagger.io/)
* [VSCode Swagger Viewer](https://marketplace.visualstudio.com/items?itemName=Arjun.swagger-viewer)
* エディタはなんでも良いですが最終的に生成したAPIがvalidかどうか確認する必要があります

### multi-file-swagger
* [multi-file-swagger](https://www.npmjs.com/package/multi-file-swagger)
* APIのPathsやComponentを共通化、リポジトリ管理するために分割をしています。分割したYAMLファイルを結合するために使用しています
* プロジェクトでは自動テスト直前に自動結合させて常に最新の仕様書でテストを走らせています。

### OpenAPI Generator
* [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator)
* API仕様書のhtmlドキュメントを生成するために使用
* 一部OpenAPI3の構文に対応していない箇所がありOpenAPI Generatorに合わせた書き方をする必要があります。
* プロジェクトではCIでテストがGreenになったら最新のhtmlドキュメントをS3にアップロードし開発者以外がAPI仕様を閲覧できる状態にしています。

### committee
* [committee](https://github.com/interagent/committee)
* API仕様書をもとにリクエスト/レスポンス形式をチェックするライブラリです。現在も開発が活発でOpenAPI3に対応したのをきっかけに導入を決めました。

## まとめ
* 次回はスキーマ分割とAPI/クライアントの自動テストを書きたいと思います
bashで「Syntax error: "(" unexpected」が表示される

# 配列処理のあるシェルスクリプトでエラーが発生

これ系のエラーはしばらく経つと忘れてしまうため調べたことの備忘録です。
他の環境で作成したシェルスクリプトが問題ないはずなのにエラーが発生。

```
Syntax error: "(" unexpected
```

環境はUbuntuでした。
シバンはbashでしてたのですがなぜかエラーになりました。
いちおう確認したらbashじゃなくてdashにつながりってます。

```
ls -l /bin/sh
lrwxrwxrwx 1 root 4 Apr 23 15:40 /bin/sh -> dash
```
bashを探すとあったのでシバンを変更したら大丈夫でした。

```
which bash
/usr/bin/bash
```

# 調べた結果
どうやらdashというのは配列が使えないシェルらしいのです。
ashというAlpine Linuxのコマンドをベースにしているようです。
だからdashという名前なんですね。
これを使いたい場合はwhileでループ処理するみたいでした。
RPAまとめ

RPAのことについて勉強してまとめたので公開します

## RPAに似たサービス
Slenium（セレニウム）等プログラミング言語やRocketMouse(ロケットマウス)
ExecelのマクロやMacOSのAutomatator(オートメーター)など

RPAが得意とするのは「頻度が多く、大量に発生する作業」です。
そして、「決められた操作を繰り返し行う」ことも得意

たとえばこの会社で経費を精算する場合、経理担当者は、①経費精算システムを起動、②経費精算システムにログイン、③申請データを表示、④メールソフトを起動、⑤メール添付で送られてきた領収書ファイルを開く、⑥申請データと領収書画像を目視で照合、⑦承認、⑧②～⑤を申請案件数だけ繰り返す、⑨ログアウト、という作業を行うとします。RPAを使えば、①〜⑨のすべてを自動化できます。

 

RPAが苦手なのは、一定でない操作が発生する作業です。

## RPAの実施工程
業務洗い出し→見える化→標準化

## RPA導入判断テスト

社内の自動化ニーズを把握する為のノウハウ

自分テスト→他人テスト→ヒアリング→導入判定

### 導入例
動画自動配信「バイトル」

## 考え方
アーリースモールサクセス
小さく早い成功

## 参照：
進藤 圭. いちばんやさしいRPAの教本　人気講師が教える現場のための業務自動化ノウハウ (「いちばんやさしい教本」シリーズ) (Japanese Edition)
Slackのincoming-webhookを使用してメッセージを投稿しよう


私の研究室ではSlackで出席確認システムが作られていて、「おは」とメッセージを投稿すると投稿時間で出席認証と「おはようございます」と返事が返ってくる。
このシステムはincoming-webhookで作られていて、アプリとして動作する。

今回、毎日「おは」というメッセージを決まった時間に自動で投稿するシステムが作れたらいいなと思ったため、開発に取り組んだ。

##1. アプリケーションの管理画面を開く
まず、ワークスペースのアカウントにログインし、アプリケーションの管理画面を開く。
スタッフのおすすめでincoming-webhookと検索し、アプリケーションを選択する。

![slack1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695304/806cccf5-e0e3-cbaf-5993-565a3c09365d.jpeg)

下の図のようなページに移動するので、Slackに追加ボタンを押す。

![slack2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695304/543e9b39-219b-0cd8-3dda-5297a4ce61d0.jpeg)

システムを導入したいチャンネルを指定し、下の図の緑のボタンをクリックする。

![slack3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695304/4ec373e0-c232-a181-d2bc-0585ccd30f90.jpeg)

セットアップの手順により、Webhook URL が得られる。
これがSlackの投稿機能APIなので、メモして控えておく。

![slack4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695304/2e76d0e0-8617-1e07-deed-5821443603e5.jpeg)

##2. アイコンと名前の設定を行う
画面を下にスクロールしていくと、アイコンと名前の設定ができるため任意で行う。

##3. シェルスクリプトによってコマンドを動かし投稿する

ターミナルからシェルスクリプトを作成する。
コードは以下の通り。

```
curl -X POST --data-urlencode "payload={\"channel\": \"#timesheets\", \"text\": \"おは\"}" https://hooks.slack.com/services/XXXXXX(メモしたURL)
```

デフォルトで用意されているのは、以下のコードである。
これは設定したアイコンをお化けで上書きしていて、名前も上書きされているため、上記のコードのように不要な部分は削除した。

```
# curl -X POST --data-urlencode "payload={\"channel\": \"#timesheets\", \"username\": \"webhookbot\", \"text\": \"これは webhookbot という名のボットから #timesheets に投稿されています。\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/XXXXX
```
このシェルスクリプトに実行権限を与え、実行させると登録したチャンネルでアプリが「おは」と投稿することが確認できる。

```
$ chmod u+x xxxx.sh
$ ./xxxx.sh
```


##4. 自動化
2020/09/10 更新

「おは」のメッセージを送るxxxx.sh(xxxxは任意)をcrontabコマンドによって自動実行させる。
少々手こずったため、うまくいかなかった原因と解決方法についても載せる。

crontabファイルには、指定した日時に実行するコマンドやスクリプトを記入する。
ファイル編集は```$ crontab -e ```のオプション: -e で行う。
(直接ファイル /var/spool/cron/crontabs/user に書いてはいけない。<userは任意設定>)

```$ crontab -e ```でファイルを開き、最後の行に日時とコマンドまたはシェルスクリプトの設定を行う。
crontabの書式は、「分」「時」「日」「月」「曜日」「コマンド」を半角スペースで区切って指定する。行頭に「#」が記載された行はコメントとなる。

```
# コメント
分 時 日 月 曜日 コマンドやスクリプト
```
例として、~/bin/ 内にあるxxxx.shというシェルスクリプトを1分ごとに実行する記入方法を以下に記述する。

```
* * * * * sh ~/bin/xxxx.sh
```
「*」はワイルドカードで全てを意味する。
このとき、xxxx.shに実行権限が与えられていない場合実行されないため、権限を与える。
↓これでもよい。

```
* * * * * sh +x ~/bin/xxxx.sh
```

このとき、注意点がある。
これでファイルに書き込みをしてもエラーが発生した。
エラーは new crontab file is missing newline before EOF, can't install. というものである。
意味は保存前のcrontabファイルと書き込みをしたファイルと比べて、書き込みをしたファイルの記述方法が間違っているということだと思われる。

解決方法を探したところ、最後に改行が必要だということが分かったため、

```
* * * * * sh ~/bin/xxxx.sh
(改行)
```

と一文改行を行ったらうまく毎分メッセージを送ることができた。

#まとめ

以上の手順でslackにメッセージを自動送信することができた。
このcrontabファイルはサーバーに置いておく。

また、8時に「おは」と送信されるようにcrontabファイルも編集する。

しかし、slackで「おは」といったら「おはようございます」と返すシステムはメンバー管理で承認されていないと反応しないため、このアプリで「おは」といっても反応してくれなかった。

crontabのいい勉強になったし、また別の活用を考えてみようと思う。
vue.js css background-image を指定

vue.js で background-image を指定したい。

```hoge.vue

<div v-if="bg" :style="{ 'background-image': 'url(' + bg + ')' }" style="padding-top: 16%;background: no-repeat center center;background-size: cover;"></div>


//略
data () {
    return {
        bg:'',

```

これで bg の値が変わるたびに 背景も変化する。
【Rails】アソシエーションの種類（1対多 / 多対多）

##脳内整理のために
プログラミング初学者がRailsを学び始めて最初に、ん？となるポイント（のはず）であるアソシエーション。
アソシエーションについて個々の記事はいくらでもあるので、全体像としてその種類を整理してみました。

##アソシエーションの種類
![アソシエーション表.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586664/66c88909-d0a7-b33b-d0aa-10cbf68c1443.png)
表の通りに分類できます。（今回1対1のアソシエーションは省略しました。）



##まとめ
- 多対多は中間テーブルが必要
- 自己結合は同じモデルを参照する外部キーが必要
Laravel8 で BindingResolutionException Target class [TestController] does not existが出力

Laravel8でコントローラーを作成しLaravel7で作成していた時と同じ感じで
下記のようにルーティングを記載しroute:listをしたところBindingResolutionExceptionが発生

```web.php
<?php

use Illuminate\Support\Facades\Route;

Route::get('test','TestController@index');

```

ドキュメント読むと下記のように修正すればOKでした


```web.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TestController;

//Route::get('test','TestController@index');
Route::get("test", [TestController::class, 'index']);

//Resourceの書き方も変わった？
// Route::resource('test', 'TestController', ['only' => ['index', 'show','update', 'store', 'destroy']]);
Route::resource('test', TestGroupController::class)->only([
    'index', 'show','update', 'store', 'destroy'
]);


```

原因はRouteServiceProviderからデフォルトnamespaceが削除されたから何ですかね？
詳しい方教えてください。


参考
https://laravel.com/docs/8.x/controllers
Maxでピーでもパーでもプーでもいいから音を出したい

#バージョン
Version 8.1.5（9359645）（64-bit windows）
#………
あたい「Max起動！」
Max「……」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/8a541263-a438-1823-70d4-7262be1ff666.png)
あたい「うーん、何をどうすればいいのか分からないぞ……」
あたい「とりあえず***ぱっちゃ～***っていうの作ってみよう（メニューの一番上にあったから多分これだ）」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/aae68524-d883-5c51-860e-754cb3a7a9db.png)

あたい「よーしできたぞ＾＾さあMaxよ、音楽を奏でるのじゃ！」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/48a4d24c-189e-a1fc-3067-de8a3346cb70.png)
Max「………」
あたい「…………」
Max「………」
あたい「もしもーし……(´◦ω◦｀)」
Max「………」
あたい「あのー……(´Ａ｀。)」
Max「………」
あたい「**音が出ない！！何もしてないのにPCが壊れた！！！！ > <**」
Max「………」（アホか…何も作ってないのに音なんか出るわけねーだろ！これで音が出たら怪奇現象だわ。壊れてんのはお前の頭だ）

#ぐぐる、触って確かめる
ピーでもパーでもプーでもいいから音出てほしいよぉ(´Д｀。)
助けてインターネット！

参考サイトさん https://yoppa.org/ssaw10/912.html

まず、Ctrl + E するたびに編集可⇔編集不可が切り替わるってわけね！
それで、メニューにあるボタンを押すと**おぶじぇくと**が追加されると…。
オブジェクト内で文字を打つと補完してくれる訳か～。ふむふむ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/09c1dbbf-74a0-5904-c4af-0057d1df2d2d.png)
オブジェクトの追加は`空いているスペースでダブルクリック`でもOKと。


**cycle～** がなんか音を出すっぽいオブジェクトだということは分かったわ！（大雑把すぎ）
でもこれだけじゃダメみたい。**この高さの音を出せ** って命令をcycle～君に渡してあげなきゃいけないらしい。確かにいきなり「音を出せ」って言われても「どんな音出せばいいんじゃい！」ってなるもんね。

cycle～の後にスペース押すと引数の内容を教えてくれることを発見。
1番目の引数が周波数になるってことか～。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/bf3e7e2a-8916-80c2-f462-4d187e76af18.png)

とりあえず **800っぽい音を出せ！** って引数をセットしてみました＾＾
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/78a4b46c-57f8-d91f-df65-0b2635f5d0c4.png)
でもまだ音が出ない…。

あ、そっか **最終的な音の出口** を設定してあげないといけないんだね。
いろんなオブジェクトがいっぱいあったら「結局どっから音出せばいいんじゃい！」ってなるもんね。
ということで、オーディオの出口のパーツを追加！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b9275fa2-6483-91c0-fbee-e7a9a736c82a.png)
cycle～君とオーディオ出口君を結合♥
準備完了！これで音が出る、はず。（多分）
（cycle～君が作った音は左下から出てくる、オーディオ出口君が2箇所で音を受け取っているのは、スピーカーが左右2つあるから）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/dac17b34-2490-b783-8be3-63449958d8d7.png)

上で信号を受け取って処理結果を下へ流すっていうのがMaxのオブジェクトの基本的な流れ。

#初めての音♥
いきなり音量MAXで変な音出てスピーカー吹っ飛んじゃったら怖いから、右下のボリュームを下げておこっと。**Max** なだけに！
Max「……」（はよやらんかい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e13f0d1e-c9ca-a746-c2d8-aaa061ed3b7d.png)
右下の電源ボタンを押すとスピーカーアイコンが点灯！
音量を徐々に上げていくと……
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/985a32f7-1d29-fdb3-393f-20338ab4e83e.png)

Max「ポーーーーーーーーーーーーーーーーーーー」
あたい「やだ、音でちゃった///…………うーん、心停止みたいな感じだけどまあよしっ！今日はこのくらいにしといてやるっ！！」
Max「ポーーーーーーーーーーーーーーーーーーー」（こんなんでいいのかよ…。先が思いやられるわ。てかいつまで鳴らすんじゃい……）

#次の記事
[Maxでランダムな高さの音がピコピコ鳴るものを作る](https://qiita.com/waokitsune/items/d87e1b3c6b013f099333)
localhostのみアクセスできるサービスをnginxで中継する

# 概要

`localhost`指定でしか応答しないサービスに対しでnginxによる中継を行い、サービスを利用する。
Websocket対応。

# 環境

- Windows 10

# インストール

http://nginx.org/en/download.html より適当なバージョンをダウンロードし、展開する。

# 設定ファイル

元の `nginx.conf` を `nginx.conf.bak` 等に名前を変えバックアップ後変更する。

`Host` の指定をしなければ自動的にアクセス元がnginxホストとなる。

### nginx.conf

```
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''  close;
    }

    server {
        listen       80;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        location / {
            proxy_pass  http://localhost:18080/;
        }
    }
}
```


# 参考

- [Windowsにnginxをセットアップする](https://qiita.com/tatuno/items/44ec8130d7544d1534f7)

- [NginxのリバースプロキシでWebソケットを通す際の設定](https://qiita.com/YuukiMiyoshi/items/d56d99be7fb8f69a751b)
Automation Anywhere A2019 - MS Accessデータベースの利用

#MS AccessデータベースにA2019からアクセスしてみる

MS Access。ものすごく久しぶりに触ってみました。
今はmdbではなく、accdbというのが拡張子なんですね。

さて、Automation Anywhere A2019からMS Accessへのアクセスは、
標準で用意されている「データベース」パッケージでアクセスが可能です。

##接続設定

特に難しい設定は無く、単純に「データベース：接続」アクションをドラッグ＆ドロップして、
データベースタイプとして「Microsoft Access」を指定。
データベースファイルパスとして、「デスクトップファイル」を選択しながら、.accdbファイルを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/c3c7d0ab-1451-6649-51e7-103a0c370c8c.png)

#クエリー①
Select SQL文を実行するには、「データベース：読み取り」ステップを利用します。
「SELECTステートメントを入力」のところに、Select文を記載します。
項目名にスペースが入っている場合は、[]で囲むと良いですね。

この時、「CSVにデータをエクスポート」にチェックを入れてファイルを指定して置くと、クエリーした内容がCSVファイルとして出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/ae9347c4-071d-7dd9-a42b-ae72ef96b61c.png)

###クエリーしたデータの利用
では、「データベース：読み取り」でクエリーしたデータをBotの中で利用したい場合にどうするか。

答え：　「ループ」を利用します。

ループの選択肢に、「SQLクエリ Datasetの各行に対して」という選択肢があります。
Excelの時と同じように、レコード型の変数に各行の値が入るようです。

この時、SQL文で指定した項目が先頭から0,1,2・・・というインデックスになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/3d15dd32-912d-27fa-c1b1-1a174f04139e.png)

##クエリー②

より複雑な処理をBot内で実行する場合は、「データベース：Export to data table」が使えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/6aef257b-7877-53d1-7c8f-38d4bf1be09e.png)

こちらの方法では、データテーブル型の変数に値が格納されますので、
データテーブルパッケージや、ループのデータテーブルの各行といった処理も可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/0206d5e8-2bf7-930d-fe06-7b44cee66b7c.png)

#その他の操作
他にも、「挿入／更新／削除」といったアクションや、トランザクションの開始／終了等、ストアドプロシージャの実行など、
一通りのデータベース処理が可能となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/d26e7572-d3d3-6559-e8c7-8d79359f7eb0.png)
vue router

#routerの初期設定
npm install vue-router

srcファイルにrouter.jsを作る

main.jsでrouterのインポート登録

router-viewの記述

active-class
exact

ボタンでurlの移動
this.$router.push('users');

動的にurlを操る
コロンをつける
path:'/users/:id'

idにアクセスする
{{$route.params.id}}

props:true
props:["id"]
で、idだけで表示できるようになる

childrenでrouter-viewをネストすることができる

v-bindで動的にurlを変える

```
<router-link :to="'/users/'+(Number(id)+1)+'/profiles'">
```


名前月つきルートを使う
```
<router-link :to="{name:'users-id-profile',params:{id:Number(id)+1}}">次</router-link>

{path:"profiles",component:UsersProfiles,name:"users-id-profile"},
```

名前をつけると、同じページでいろんなrouter-viewが使える

```
routes:[
    {
        path:'/',components:{
        default:Home,
        header:HeaderHome
    }
```

名前つきrouter-viewを使うときはpropsをオブジェクトにする

```
 props:{
            default:true,
            header:false
        }
```
AWS CloudFrontのキャッシュ設定が新しくなっていた


## 概要

* 以前は CloudFront ではキャッシュ設定を個別のパスに対する Behavior でTTL設定などを毎回設定する必要があった
* 設定に`Use a cache policy and origin request policy`の選択肢が現れ、cache policy を作って使い回せるようになった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/295ef624-8ab0-3371-b41b-f73d8637afaa.png)

## もっともベーシックなCache Policy と Origin Request Policy

以下のようにすでに組み込み（Managed）な Cache Policy が利用可能です。
既存の Policy の設定を見ることで、どういう設定ができるかみていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/6ee56ad6-bfa0-a13c-5578-ec28a5267dfc.png)


#### Cache Policy

* Managed-CachingOptimized
    * TTL Settings
        * 設定値
            * Minimum TTL => 1
            * Maximum TTL => 31536000
            * Default TTL => 86400
        * 意味
            * サーバサイドから返しているキャッシュ関連ヘッダ（Cache-Control max-age など）とTTLの関係については[こちら](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Expiration.html)が参考になります
            * `Cache-Control max-age` がサーバサイドから帰ってきているケースだと、TTLのレンジに収まっていればそれが使われ、収まっていなければTTLが優先されるようです
            * CloudFrontがレスポンスヘッダを書き換えるわけではないので、クライアントから見える `Cache-Control max-age` が書き換わっているわけではないので、実際に設定したTTLが適用されているかは確認できませんでした
    * Cache key contents （The cache key includes the headers, cookies, and query strings in the cache policy, as follows）
        * 設定値
            * Headers => None
            * Cookies => None
            * Query strings => None
        * 意味
            * CachingOptimizedという名前がついている通り、上記の設定が一番最適化されたものです
            * レスポンスヘッダ、クッキー、クエリストリングの特定のものが入っているかどうかでキャッシュを分岐することができますが、それを設定しないということは、全てのリクエストが同じパスであれば同じキャッシュを見ることを意味します
            * ファイルを差し替えるとき、ファイル名を変更しないでクエリストリングだけ変更してキャッシュ揮発させることを期待している場合には、 `Query Strings`の設定は`None`ではダメで、`All`設定をいれておかなければいけないと思います

#### Origin Request Policy

* Managed-AllViewer
    * Origin request contents
        * 設定値
            * Headers => All viewer headers
            * Cookies => All
            * Query strings => All
        * 意味
            * オリジンサーバに対してCloudFrontからどの情報を流すかを示しているようです
            * `Headers`の`All viewer headers`は、クライアントが送ってきたヘッダをそのままオリジンに渡す設定です。Origin Request Policy を新たに作成すれば、CloudFrontが後から付与するヘッダなどもオリジンに流せるようです


## キャッシュ設定の反映確認

キャッシュ設定をする前は以下のように Miss From cloudfront になっていると思います。

![image1https___qiita-image-store_s3_ap-northeast-1_amazonaws_com_0_144064_0b12415c-35ae-49ef-28fd-5650ffc9c2bf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/54f49a8c-b7e5-3004-2595-2a27dcaa54ae.png)

Hit from CloudFront になります。

![image2https___qiita-image-store_s3_ap-northeast-1_amazonaws_com_0_144064_0f3e685a-fb44-a527-a758-e5ab8041c4d4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/cc2cea7c-b6bd-59e5-0ad6-2358e499056c.png)
【初心者でもわかる】簡単！ HTMLのタグをそのままテキスト（文字）として表示する方法

# どうも7noteです。HTMLソースをそのまま表示させる方法です。超簡単。

どうも7noteです。
この記事は以下へ引っ越しました。

https://naruweb.com/coding/htmltag/
【Ruby】関数における例外処理

## はじめに
この記事は数多ある例外処理についての補足的なものです。具体的には、記事で紹介されてないパターンについて検証した結果を残します。

## 環境
- Mac
- Ruby 2.6.3

## 関数の中での使用

関数の中では以下のように書けます。

```ruby
def method
  puts "hoge"
  a = 1 / 0
rescue ZeroDivisionError
  puts $!
end
```
begin, endを省いた形ですね。このような形の場合、

```ruby
a = 1 / 0
```
がエラーを発生させるであろうことは一目瞭然です。しかし、以下の場合であればどうでしょうか。

```ruby
def method
  # 膨大な処理1
  # エラーが発生しそうな処理
  # 膨大な処理2
rescue StandardError
  puts $!
end
```
さて、このコードを見た人がすぐにエラーの発生しそうな処理を見抜けるかというと怪しいところです(メソッド分割しろや、という話は事情があって無理だという前提で)。その場合はあえてbegin, endを書いたらいいと思います。

```ruby
def method
  # 膨大な処理1
  begin
    # エラーが発生しそうな処理
  rescue StandardError
    puts $!
  end
  # 膨大な処理2
end
```
こうすればどこがエラー発生しそうか分かりますし、沢山スクロールしてrescueを見に行く必要もありません。
ちなみにrescueでreturnすると膨大な処理2は処理されないので、間違いなく処理してほしいならensureに入れましょう。

```ruby
def method
  # 膨大な処理1
  begin
    # エラーが発生しそうな処理
  rescue StandardError
    puts $!
    return
  ensure
    # 膨大な処理2(rescueにreturnがあっても処理される)
  end
end
```

もしエラーの発生しそうな処理が複数ある場合は、関数の最後にまとめて書くのがシンプルでいいと思います。毎回begin, rescue, end書くのは流石に可読性下がりますので。何事も適切に。

```ruby
def method
  # いろいろエラーが発生しそうな処理

  # その他処理

rescue ZeroDivisionError, ArgumentError
  puts $!
rescue StandardError
  puts $!
  puts $@
end
```
ちなみにStandardErrorを先に書くと大体のエラー処理はこいつがやってしまいます。なので子クラスから書いていきましょう。
【Python】CSVファイルの読み込み

```csvfile.csv
Aさん,1,月
Bさん,2,火
Cさん,3,水
```
```python:main.py
import csv

#ファイルの読み込みを行います
csv_file = open("csvfile.csv", "r", encoding="utf-8", errors="", newline="" )
print(type(csv_file))
"""
<class '_io.TextIOWrapper'>
"""

#CSV文字列をパースします。　
csvData = csv.reader(csv_file, delimiter=",", doublequote=True, lineterminator="\r\n", quotechar='"', skipinitialspace=True)
print(type(csvData))
"""
<class '_csv.reader'>
"""

#_csv.reader型をリストに変換
csvData = [row for row in csvData]
print(type(csvData))
print(csvData)
"""
<class 'list'>
[['Aさん', '1', '月'], ['Bさん', '2', '火'], ['Cさん', '3', '水']]
"""
```
Chrome拡張で contentSettings パーミッションを試してみた

# contentSettings パーミッションを試してみた
`manifest.json` で `permissions` に `contentSettings` を含めておくと拡張インストール時の許可さえ得てしまえば、カメラやポップアップの許可設定を拡張側から確認ナシに変更できる。

## 拡張ポップアップアクション内でカメラを使う許可を取得する

やりたかったのは拡張のポップアップ内でカメラを使いたかっただけなんだがそれを `contentSettings` 権限を利用して実現するのをとりあえず試してみた。とりあえず以下のような感じで許可を得られた。

```js
chrome.contentSettings.camera.set({
  primaryPattern: chrome.runtime.getURL('/*').replace(/^.*?:\/\//,'*://'),
  setting: chrome.contentSettings.CameraContentSetting.ALLOW, // 'allow' という文字列
  scope: 'regular'
})
```

注意点としては `primaryPattern` にバカ正直に `chrome-extension://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/*` をセットしようとすると `Invalid scheme.` と怒られてエラーになってしまう。そこで `*://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/*` を指定してみたところこれは通ってしまった（それでいいのか…？）。とりあえずこれで目論見通り自分の拡張のポップアップURLに対してちゃんと許可を得ることが出来た。

## 結論： contentSettings パーミッションは強力すぎるので使わない事にした
しかし自分の拡張内でカメラ許可を得るためだけだと `contentSettings` パーミッションは強力すぎるので他の手段を検討したほうが良いという結論になった。例えば適当な拡張内のURLを新しいタブで開いてそこで確認ダイアログを出して許可を得られれば必要十分の結果が得られる。

そもそも manifest.json の仕様には `videoCapture` という定義済みパーミッションがあるとされているが少なくとも現時点(Chrome86)ではこれを指定しても何の意味も無いようだ…。

ちなみに、どのへんが強力すぎるかというと『各種機能の権限設定で `https://*/*` に対して `allow` を設定とかを確認無しでセットする』とかがあっさり出来てしまうので…。


# 参考：前提として権限のチェック方法

```js
const permissionStatus = await navigator.permissions.query({name:'camera'})
```

で `PermissionState` オブジェクトが取得できて state プロパティに `granted` / `prompt` / `denied` のどれかの値が入ってくる。

`navigator.permissions.query` がダイアログを出さずに権限の確認だけを行う方法で、その結果が `granted` 以外だった場合は権限の要求が必要なので、以下のコードで権限要求のダイアログを出す。

```js
const permissionStatus = await navigator.permissions.request({name:'camera'})
```

これを実行するとブロックするか許可するかのダイアログが出てくる（ただし拡張のポップアップページなどでは実行してもダイアログは出てこない）ので、何かしらアクションをすると query のときと同じように `PermissionState` オブジェクトが返ってくる。許可を押した場合は `granted`、ブロックした場合は `denied`、バツボタンでダイアログを閉じて終わった場合は `prompt` な state が得られる。

# 一度ブロックされてしまった場合の対処法
ここで問題なのはブロックされた場合で、一度ブロックされるとブラウザの設定画面からブロックの解除をしてもらわないといけないのが非常に面倒。ブロックされたときに再要求をする手立て(API)は用意されていない。なのでわかりやすい説明ページを用意するくらいしか出来ない。

## contentSettings権限がある場合はブロックを覆せる
contentSettings 権限を持った拡張の場合は一度 denied されたサイト設定を allow で上書きマスクして覆すことが出来る。（サイトに対するブラウザの設定値を上書きするのではなくブラウザの設定値を無視して拡張で作成したサイト設定を強制的に適用させるイメージ）
その効果は拡張がインストールされている限り有効で、サイト設定を上書きした拡張がアンインストールまたは無効化された場合は拡張による上書きマスクがなくなって、元の値が有効になる。
[Rails] ActiveRecord::HasManyThrough Order Error in Users#show

#環境
Rails 6.0.3.2
ruby 2.6.5p114 (2019-10-01 revision 67812)
vscode

#本稿の趣旨
https://qiita.com/tenitiumai/items/3d9466d7a24197f690bb　
を参考にしてDM機能を作成することを目標とする。

　しかし、本稿は、エラーの解決方法を紹介するため、
具体的なDM機能の作成手順については割愛する（上記の参考記事を参照していただきたい）。

#該当のエラー
![スクリーンショット 2020-09-09 12.51.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650686/6155eaf5-2759-8d9d-c1ae-6734520e054c.png)

#エラーの原因
参考記事　https://qiita.com/krppppp/items/0db4184e9df553f05048
これは、　Cannot have a has_many:through association 'User#followers' which goes through 'User#follower_relationships' before the through associations is defined. に注目する。
どうやら、モデルの配置順序が間違っていることが原因である。
具体的には、follower_relationshipｓが読み込まれる前にfollowersが読み込まれているため、エラーが生じていると推測できる。

#解決方法
コードを見ると、

```app/models/user.rb

  has_many :followers, through: :follower_relationships
  
  has_many :follower_relationships, foreign_key: "following_id", class_name: 
  "Relationship", dependent: :destroy
  
  has_many :followings, through: :following_relationships
```

となっており、followersが、follower_relationshipsより上にある。これを

```app/models/user.rb

  has_many :followings, through: :following_relationships
  
  has_many :follower_relationships, foreign_key: "following_id", class_name: 
  "Relationship", dependent: :destroy
  
  has_many :followers, through: :follower_relationships
```
とすれば、解決するのではないか。
DMボタンを配置したユーザー詳細ページにアクセスすると、
![スクリーンショット 2020-09-09 13.15.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/650686/91d966ff-578a-6b76-cd54-65e9f60a73e3.png)

無事解決しました。

#おわりに
モデルの順序でエラーが生じることになるとは思わなかった。
これからはその点も意識していこうと思いました。
Laravel MySQL 既存カラムのNULL許容とデフォルト値をNULLに設定する

# 目的

- LaravelとMySQLの組み合わせで「カラムへのNULL格納を許容する」と「デフォルト値をNULLに設定する」方法をまとめる。

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2GHzクアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHPバージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravelバージョン | 7.0.8 | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

# 前提条件

- マイグレーションをすることができる状態のLaravelアプリが存在していること。

# 前提情報

- 本記事では都合上、マイグレーションファイルのカラムに変更を与える処理のみ記載する。
- 本来はマイグレーションファイルの作成、マイグレーションファイルの記載、マイグレーションなどの作業が必要である。

# 例

- 下記の内容をマイグレーションファイルのupに記載する必要がある。
- マイグレーション後から現在の状態に戻すためのdownの処理も記載する必要がある。
- nullの許容設定のマイグレーションファイルへの記載文を下記に記載する。

```php
// nullを許容したい時
$table->カラムタイプ('カラム名')->nullable()->change();

// nullを許容しない時
$table->カラムタイプ('カラム名')->nullable(false)->change();
```
- デフォルト値null設定のマイグレーションファイルへの記載文を下記に記載する。

```php
$table->カラムタイプ('カラム名')->default(null)->change();
```

# 参考文献

- [Laravel 7.x データベース：マイグレーション](https://readouble.com/laravel/7.x/ja/migrations.html)
【PHP】コメントを書くとき、書かないとき

##コメントはどうあるべきか？

コメントは、読んですぐに理解できるような、簡潔で、正確なものであるべき。
それはわかるのですが、すべての処理に書いていたら
ソース全体が読みにくくなってしまいます。

コメントも整理が必要だ。

##いらないコメントと必要なコメント

見ればわかるようなことはコメントに書かない方がいい。

```php
// 人間かどうかを判断
if ($object->isHuman() === true) {
	// 名前をタロウにする
	$name = 'tarou';
}
```
メソッド名や変数名などの助けもあって、明らかに処理の内容がわかるとき、
わざわざコメントする必要はないと思います。読めばわかるので。

コメントが必要なのは

**・なぜこうなるか
・なにをしているのか(これはなにか)
・勘違いしないか**

自分が初めて見るコードだと思って見たときに、
この3点で引っかかりそうならコメントを書くようにしています。

####なぜこうなるか
```php
// パスワードがない＝本登録していないため対象外
if (empty($user->password)) {
	return false;
}
```
なぜこうなるのか。パスワードがないから対象外なのではなく、
本登録ではないから、ということが重要な事項の場合があります。
そういった場合にコメントを入れています。

###これはなにか(なにをしているのか)
```php
// すべての注文額を合計する
$total_amount = array_sum(array_column($orders->toArray(), 'amount'));
```
PHP関数やフレームワークの持つヘルパ関数などが組み合わさり、
一見してなにをしているのかがわかりづらい場合など、コメントを入れています。

これについては私がプログラム初心者なので、ソースに対する理解度が低く、
入れているということもあります。
ただ、保守などで、今後どういう理解度の方がこのソースを見るかわからないので、
念のためという面もあります。

###勘違いしないか
```php5
// 管理者へメール(請求管理者とは別なので注意)
$this->sendMailToAdmin($from, $subject, $body);
```

この場合だと、請求も含んだ処理をしていて、2つの宛先がややこしいなー、
というように感じたので入れています。
間違えてしまいそうだが、決して間違えてはいけないもの
(そんなことばかりですが)、に入れるようにしています。


1年間プログラムをやってきた所感、という内容なので、
ご意見ありましたら頂戴したいです。
rebase時のコンフリクトでリベース先の変更だけ適用する方法

# Rebase対応にて、コンフリクトした場合、リベース先の変更を全て取り入れる場合
いろいろあって、リベース先の変更を全て入れないといけなかったのでメモ

## TL;DR
```
git checkout --ours <ファイルパス>
git add <ファイルパス>
# コンフリクト全て対象で良いなら、<ファイルパス>部分を . 指定でOK
```

## 検証してみる

まずmasterブランチで何もないファイルを作成してcommit

devブランチを切る

```
$ git checkout -b dev
```

devブランチでsample.txtを以下の内容で保存


```sample.txt
aaa
```

masterブランチに移動してsample.txtを以下の内容で保存

```sample.txt
bbb
```

これでコンフリクトする。

devブランチに移動してrebase

```
$ git rebase master
```

バッチリコンフリクトした

```
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: change sample.txt on dev
Using index info to reconstruct a base tree...
M       sample.txt
Falling back to patching base and 3-way merge...
Auto-merging sample.txt
CONFLICT (content): Merge conflict in sample.txt
error: Failed to merge in the changes.
Patch failed at 0001 change sample.txt on dev
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
```

## リベース先の変更を入れる
今回の場合はmasterブランチの内容を入れる

```
$ git checkout --ours sample.txt
$ git add sample.txt
```

これでOK！

## ちなみに...
rebase元（今回で言うとdevブランチ）の内容を反映する場合は、

```
$ git checkout --theirs sample.txt
$ git add sample.txt
```
で良い。
【C#】競技プログラミング 入出力処理

#入力
##文字列1行
```C#
string str = Console.ReadLine();
```

## int配列
```C#
int[] array = Console.ReadLine().Split().Select(int.Parse).ToArray();
```

## long配列
```C#
long[] array = Console.ReadLine().Split().Select(long.Parse).ToArray();
```
`Console.ReadLine().Split()`までの部分で関数を作っておくと良いかもしれません。

## N Mなどの複数の時
以下のクラスをコピペして貼る。
（atcoder社長のchokudai氏の利用しているScannerを一部改変したもの）

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">C#は普通に競技プログラミングで世界１位十分狙えるポテンシャルのある言語だと思うので、そのまま続けてくださいな！<br>もし入出力とかの煩わしさが気になってたら、この提出の下の方にある適当に作ったScannerクラスをコピペして使ってもらえば大丈夫ですよ！<a href="https://t.co/TWyP6gwGfN">https://t.co/TWyP6gwGfN</a></p>&mdash; chokudai(高橋 直大)🍆🎪🐦 (@chokudai) <a href="https://twitter.com/chokudai/status/1051741812501536769?ref_src=twsrc%5Etfw">October 15, 2018</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

```C#
class Scanner
{
    string[] s;
    int i;
    char[] cs = new char[] { ' ' };
    public Scanner()
    {
        s = new string[0];
        i = 0;
    }
 
    public string Next()
    {
        if (i < s.Length) return s[i++];
        string st = Console.ReadLine();
        while (st == "") st = Console.ReadLine();
        s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
        if (s.Length == 0) return Next();
        i = 0;
        return s[i++];
    }
 
    public int NextInt()
    {
        return int.Parse(Next());
    }

    public long NextLong()
    {
        return long.Parse(Next());
    }
   ```

使い方

```C#
var scanner = new Scanner();
//N M K
int N = scanner.NextInt();
long M = scanner.NextLong();
string K = scanner.Next();
```

#出力
## 基本
```C#
//改行も入ります
var num = 20;
Console.WriteLine(num); 
Console.WriteLine("Yes");
Console.WriteLine("No");
```

## フォーマット
```C#
var n = 12, m = 24;
Console.WriteLine("{0} {1} {2}", n, m, 4 + 4);
```

変数名直接(古いコンパイラでは対応していないかも)

```C#
var n = 12, m = 24;
Console.WriteLine("${n} ${m}");
```

## 配列
```C#
var array = new int[]{ 20, 30, 22, 11 };
//コンマ区切り
Console.WriteLine(string.Join(",", array));
//スペース区切り
Console.WriteLine(string.Join(" ", array));
//改行区切り
Console.WriteLine(string.Join("\r\n", array));

```

foreachを使ったやつ。atcoderだと、一番最後に空白あっても問題ないため

```C#
var array = new int[]{ 20, 30, 22, 11 };
foreach(var a in array)
{
	Console.WriteLine("{0} ", a);
}
```