OmniAICreator/Qiita-1.07M huggingface dataset:
[Android]ViewModelのドキュメントを読んでも分からなかった人に贈る～シン・ドキュメント～

#この記事は
[こちらと共にご覧ください](https://developer.android.com/topic/libraries/architecture/viewmodel?hl=ja)
実装方法よりも仕組みを掘り下げてViewModelが、一体なんなのかがわかるように解説していきます。
コードについては、殆ど触れてません。
コードラボに書き方に関しては充実していると思います。
そして、前提としてView-ViewModel間の関係をお寿司屋の「客」と「板前」に例えて解説していきます。

#ViewModelとは
>ViewModel は、ライフサイクルを意識した方法で UI 関連のデータを保存し管理するためのクラスです。ViewModel クラスを使用すると、画面の回転などの構成の変更後にデータを引き継ぐことができます。

このようにあります。
画面には、ライフサイクルというものがあります。
これは「人生」みたいなものですね。
つまり、画面には誕生してから、時には鬱になったり、はたまた復活したり、そして死ぬというプロセスがあるということです。
現実的には、まぁスマホを使っているとよくアプリ間を行き来することがあると思いますが、その際にアプリのシステムによって画面を停止や再開、破棄など状態が変化しているという事です。
本来それは、システムが知っていることなのですが、ライフサイクルを意識しているというのは、ライフサイクルメソッドを通じて、それらの画面の状態を知っているということになります。

話がそれました。
簡単に言うと、画面にも「人生」があって、色々ある。
ということが分かれば良いです。

ViewModelというのは、画面で使われるデータを保存して、管理する役割があります。
例えば、TextViewやBottomViewにセットする文字列やViewの表示・非表示のためのBoolean等。

さて、冒頭でView-ViewModel間の関係をお寿司屋の「客」と「板前」の関係と捉えました。
これをもう少し詳しく説明すると、「分業」を再現しているという事です。
お寿司やでは、お寿司を食べる「客」とお寿司を握る「板前」が存在しています。
この「分業」があることで、円滑にお店が回っているわけです。
逆に、「分業」がないと、「客」がセルフサービスでお寿司を握ることになってしまします。（それは、それで面白そうだが）
つまり、「客」の負担が増えてしまいます。

このことについて、ドキュメントの抜粋を見てみましょう。

>アクティビティやフラグメントなどの UI コントローラの主な目的は、UI データの表示、ユーザー操作への対処、オペレーティング システムとのやり取り（権限のリクエストなど）を行うことです。UI コントローラに対してデータベースやネットワークからのデータ読み込みも行うよう要求すると、クラスが肥大化することになります。 UI コントローラに過度の役割を割り当てると、アプリの作業を他のクラスに任せずに 1 つのクラスですべて処理しようとすることになり、テストも極めて困難になります。

UIコントローラというのは、ドキュメントの文言からして、「客」（View）の事と捉えて大丈夫そうです。
ActivityやFragmentが必要以上の処理することは、クラスの肥大化を招いてしまうので、良くないよね！
と、「客」の負担が増えてしまうことを懸念していることがわかるかと思います。

ドキュメント内のViewModelを実装するの段落で、実際にコードが書かれているかと思いますが、
LiveDataが出現して解説がややこしくなるので、コードに関しては割愛します。

とりあえず、ViewModelクラスを継承すれば「板前」になれる。
そして、View側には
`val model: MyViewModel by viewModels()`
と記述することによって依存関係を繋ぐことで、まるで「板前」さんの「出勤」が完了されることだけ分かれば十分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599059/4ddd4678-6328-6fd1-2c81-0736e9876cd8.png)

さてさて、最初の方に少しだけ触れたViewModelの「人生」、ライフサイクルについて、掘り下げていきたいと思います。
ドキュメントでは、上記の図式とともにActivityとViewModelのライフサイクルの対応について書かれています。

これは、お寿司屋的には「客」が来店して、注文し、食事したり、会計をしたりして帰るまで、「板前」はずっと付きっきりというわけです。

>アクティビティが終了して破棄されるまで存在します。

ドキュメントでは、このように表現されていますね。
ちなみに、最後のonClear()メソッドはViewModelの消滅を意味します。
板前さんの「帰宅」ですね。

と、こんな感じで良いですかね。
その後のFragment間でデータを共有することに関しては、「客」間で、お寿司のデータを共有するときは、ActivityスコープのViewModelを用いると良いよ！と言っています。

そのあとは、コルーチンの話で ViewModel単体のお話で無くなるので以上にしたいと思います。

#終わり
実際に実装するとなると、もうちょい仕組みの理解が必要ですかね。
下記、記事が書き方に関してわかりやすいかなと。
ただ、ViewModelProvidersの書き方あんまり馴染みない・・・

https://medium.com/androiddevelopers/viewmodels-a-simple-example-ed5ac416317e


こんな感じの記事を今後も書いていきやす。
また、ツッコミお待ちしております！
HTTPS通信でアクセス可能にする

#####前提条件
・ELB、EC2２台（各AVゾーンに１台ずつ）、RDS
・ROUTE５３とELBのドメイン紐付け
・EC2にwordpressインストール済み、ページが表示されていること


####①ELBのリスナー（通信を受け付けるポートの許可設定）の設定
・ロードバランサーのリスナータブへ移動
・プロトコル：HTTPS
・デフォルトアクション：転送先、設定してるターゲットグループ選択

####②新しいACM証明書をリクエスト
**ステップ１：ドメイン名の追加**
ドメイン名入力し次へ

**ステップ２：認証方法の選択**
DNS検証を選択し次へ

**ステップ３：必要に応じてタグ設定**
**ステップ４：確認**
**ステップ５：検証**
ROUTE53でのレコードの作成ボタンを押す
→CNAMEレコードが追加される→続行
→ROUTE53のコンソール画面で追加されていることを確認

####③ ①のステップへ戻り、SSL証明書が選択できるようになっているので、②で発行した証明書を選択

####④ELBのセキュリティグループにHTTPSを追加

####⑤wordpressの設定
・EC2へログインし、/var/www/htmlへ移動
・llコマンドで階層の中を確認
・wp-config.phpの中身を編集
・「編集が必要なのはここまでです」というコメントの上に下記のコードを追加

`if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $_SERVER['HTTPS'] = 'on';
  $_ENV['HTTPS'] = 'on';
}
`
・もう一つのEC2にも同じ設定をする

####⑥ドメイン名でWebページにアクセスし、HTTPS通信できているか確認
＊表示が崩れている場合
DB保存情報のsiteurlとhomeを ‘https://[独自ドメイン名]’ に変更する。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
（**手順**：
・EC2からRDSへアクセス
ー`mysql -h RDSのエンドポイント　-u ユーザー名　-p`
ー`パスワード入力`

・ルーザー名のテーブルへ移る
`USE テーブル名`

・現在のテーブル設定の確認
`SELECT * FROM wp_options WHERE option_name IN ('siteurl', 'home');`

・下記のコマンドで設定変更
`UPDATE wp_options SET option_value = 'http://xx.xx.xx.xx' WHERE option_name IN ('siteurl', 'home');`

xx.xx.xx.xxの部分に独自ドメイン名を指定）
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

####⑦セキュリティを強化するため、ELBのセキュリティグループでHTTP通信を削除

####⑧ELBリスナーのHTTPも削除

####⑨再度Webページを確認し、ちゃんとHTTPS通信が出来ていれば完了
Flutterでキャッシュに保存したファイルを開く

## about
「Flutterで端末のキャッシュ領域に保存したファイルを開く方法」が見つからず苦労したのでまとめました

- Android/iOSのアプリ用キャッシュ領域にファイルを保存
- 端末デフォルトビューアで開く

`path_provider`でパスを取得して`open_file`で開けばOKでした。

## 経緯
実装のコンテキストは以下

- 要件
  - AWS S3にアップロードしたPDFを端末に保存するとき、オリジナルのファイル名にしたい
- 問題
  - S３に上げた時点でランダムなファイル名になる
  - そのまま開くとランダム名で保存することになる

- 解決案
  - 一度キャッシュ領域に、指定した名前で保存
  - そのファイルを開けば端末のPDF Viewerで保存したときもファイル名のハンドリングが可能
  - (URLをPDF Viewerに渡す場合と違い、ダウンロード完了まで開けなくなります)


## sample
サンプルプロジェクトは以下
https://github.com/kanari3/cache_and_open_document_flutter

path_providerのサンプルアプリに、今回の要件を追加した形になっています。

<img width=300 src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275986/9e4936b2-a53b-f567-47d3-44196fa5b4df.png>

## 方法
`open_file`を使えばOKです
https://pub.dev/packages/open_file

url_launcherで開こうとしていました。

OpenFile.open()でパスを渡せばOSに応じて適切に解釈してくれます。
typeとutiのオプションをつけることもできます。

## 大変だったこと

### url_launcherが、内部領域へのアクセスに対応していなかった
URLを渡してビューアを開くときに使っていたので、url_launcherで検証していました。
保存したパスを渡して検証していましたが、必ず例外に入るようです。
※ 上手く設定すれば file://やcontents://でアクセスできる方法があるかも:thinking:

https://pub.dev/packages/url_launcher

### Android / iOS両方に対応したい
結果としては、path_providerを使えば楽
OS毎にメソッドチャンネルを書こうとしていた。

### 試行錯誤中はいろいろな保存先を試す必要があった

キャッシュ領域への保存はできるが、読み出しがうまくいかなかったので
`/sdcard/`以下に保存することも考えた。(Android)
この場合、パーミッション管理とiOSの分岐が必要になる。
また、閲覧しただけで保存までされてしまうので削除が必要になる。

## おわり

ググり力が足りなくて1日溶かしてしまった。
既存プロジェクトでいろいろ試すコストが耐えられなくなったので、
サンプルプロジェクトを作って全パターン自動で試したりしました。
筋トレ習慣化のためのリマインドメールをGASで実現する

# 筋トレ。習慣化できてますか？

筋トレ。やろうと思い立ってなかなか習慣化できないですよね。私も大抵3日坊主でなかなか続きませんでした。。

そんな私が鈴木達也さんの「PRIDE BODY」というプログラムに出会って、
**1カ月間毎日筋トレが続いてます。**すごくないですか？

詳しくは、鈴木達也さんの「PRIDE BODY」でググってみてもらえば分かるのですが、
**「筋トレメニューをメールで毎日リマインドする」**
という仕組みがあって、私にはそのやり方が非常にマッチしていたようです[^1]。

今回はこのメールでリマインドする仕組みを、GoogleAppScript（GAS）で実現してみたので、備忘録として残します。

[^1]: 継続できた理由として、メールでのリマインドだけじゃなく、もちろん「PRIDE BODY」のコンテンツ力も大きいと思ってます。

# やりたいこと

事前にスプレッドシートに準備しておいたコンテンツをメールで配信するだけです。
簡単な構成図はこちら。
![構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236354/d029582a-98ae-a835-e7c2-08372bc0723b.png)

# 実装

早速実装の中身の話です。

### スプレッドシート例
配信するコンテンツの情報を事前にスプレッドシート上に作っておきます。
![SS例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236354/50919490-a8fa-a2be-5585-47065bee70f6.png)

* B列：リマインドしたい日付を入力します。
* C列：リマインドメールの送信者の名前を定義します。[^2]
* D列：リマインドメールの宛先を定義します。
* E列：リマインドメールの件名を定義します。
* F列：リマインドメールの本文を定義します。動画のリンクなどはここに乗せるイメージ。

[^2]: 毎回変わるものでもないので、GAS上に直接定義してもよいですね。


### スクリプト

スクリプト上にコメントは残しているので詳細な説明は省きますが、
強いて言えば、`getContentsByDate()`の中でAPIアクセスを極力減らすことを目的として、スプレッドシートの中身を2次元配列に取得しているのはポイントです。
※実際に試すとき用にコンソールログはコメントアウトして残してます。

```コード.gs
function reminder() {
  // スプレッドシートを取得
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  // シートを取得
  const sheet = ss.getSheetByName('リマインド内容');

  // 今日の文字列（yyyymmdd形式）を取得
  const today = Utilities.formatDate( new Date(), 'Asia/Tokyo', 'yyyyMMdd');
  // 今日のコンテンツを探す。
  const content = getContentsByDate(sheet, today, 2);
  // console.log(content);

  // コンテンツが取得できなかったら処理を終了する。
  if ( content === null ) {
    throw new Error('コンテンツが設定されていないようです。スプレッドシートに追加してください。');
  }

  // メール送信
  sendMail(
    content[2],  // sender
    content[3],  // email
    content[4],  // subject
    content[5]   // body
  );
}

function sendMail(sender, email, subject, body) {
  // console.log(`sender: ${sender}`);console.log(`email: ${email}`);console.log(`subject: ${subject}`);console.log(`body: ${body}`);
  // メール送信
  GmailApp.sendEmail(email, subject, body, { name : sender } );
}

function getContentsByDate(sheet, date, col) {
  // 極力APIアクセスを減らすため、スプレッドシートの中身を2次元配列に取得。
  const contents = sheet.getDataRange().getValues();

  // 1行ずつループして、今日日付のコンテンツが見つかったら配列ごと返却
  for (let i=1 ; i<contents.length ; i++) {  // 0はヘッダになるので、iの初期値は1としている。
    const searchDate = Utilities.formatDate( contents[i][col-1], 'Asia/Tokyo', 'yyyyMMdd');
    // console.log(searchDate);console.log(date);
    if(searchDate === date) {
      return contents[i];
    }
  }

  return null;
}
```

### トリガー

最後にスクリプトを毎日実行するためのトリガーを定義すれば完成です。

1. スクリプトエディタの左側のメニュー「トリガー」を押下します。
1. 右下の「トリガーを追加」ボタンを押下します。
1. トリガーの設定を添付画像を参考に設定します。
ポイントは、イベントのソースを選択を「時間主導型」にすることです。こうするとで指定した時刻（今回の場合は午前7時～8時）にリマインドメールを送ってくれるようになります。
1. 保存ボタンを押下します。

![trigger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236354/79b7f415-a029-2c03-f265-08c697588283.png)

# おわりに

「最近昔みたいにガンガン働けなくなってきたな…」とか「お腹周りに貫禄が出てきたな…」とか思ってるアラサーのあなた。
これを機に筋トレを習慣化して、健康的な身体を手に入れてみませんか？
VBA エクセル 売上のカラムで降順（値が大きい順）で並び替える


![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/5b373c4a-cc24-3981-8817-03183980ebe7.jpeg)

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/5387307d-7bed-812a-ea99-fa7dabd7f1fc.jpeg)


```vb
Sub uriage()
    Range("I4").Select 'I4セルをセレクト
    ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear '前のSortFieldオブジェクト削除
    ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("I4"), _
        SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("Sheet1").Sort
        .SetRange Range("A3:I8")
        .Header = xlGuess
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
End Sub

```
CloudFormation CodePipeline で Github v2 用コネクションを使ってGithubからソースコードを取得する


# 前置き
v1の方法はいくらでも見つかるのですが、v2の方法が、推奨だというのにも関わらずまったく見当たらないのでまとめてみました。


# やり方

結論からいえば、以下に設定値が載っています。

https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodestarConnectionSource.html#action-reference-CodestarConnectionSource-input

なんだ、``CodeStarSourceConnection`` って。Ownerも``Github``じゃないんかい。
これにたどり着くまでが長かった..


せっかくなんでやることをまとめてみます。



- コネクションを作成する
これは認証もからむのでCloudFormationでやる必要はないと思います。私はAWSコンソールからやりました。


- コネクションを使うポリシーを作成する。
これもIAMのコンソールから作成しちゃいました。CloudFormation使え > 自分
作成したポリシーをCodePipeline用のRoleにアタッチしときます。

https://docs.aws.amazon.com/dtconsole/latest/userguide/security_iam_id-based-policy-examples-connections.html

```yaml
{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "ConnectionsFullAccess",
        "Effect": "Allow",
        "Action": [
            "codestar-connections:CreateConnection",
            "codestar-connections:DeleteConnection",
            "codestar-connections:UseConnection",
            "codestar-connections:GetConnection",
            "codestar-connections:ListConnections",
            "codestar-connections:TagResource",
            "codestar-connections:ListTagsForResource",
            "codestar-connections:UntagResource"
        ],
        "Resource": "*"
     }
   ]
}

```

- CloudFormationでのSource取得ステージの書式


```yaml
  CodePipeline:
    Type: "AWS::CodePipeline::Pipeline"
    DependsOn: EcsService
    Properties:
      Name: !Ref AWS::StackName
      RoleArn: !GetAtt CodePipelineRole.Arn
      ArtifactStore:
        Location: !Ref CodePipelineS3Bucket
        Type: S3
      Stages:
        - Name: Source
          Actions:
            - InputArtifacts: []
              Name: Source
              ActionTypeId:
                Category: Source
                Owner: AWS
                Version: "1"
                Provider: CodeStarSourceConnection
              OutputArtifacts:
                - Name: SourceArtifact
              Configuration:
                FullRepositoryId: "OrganizationName/RepositoryName"
                ConnectionArn: "arn:aws:codestar-connections:ap-northeast-1:xxxxxxxxxxxxxxxxxxxxxx" #上記で作成したConnectionのARN
                BranchName: "develop"
                DetectChanges: "false"
              RunOrder: 1

```




参考になれば。
PCの電源オフ

i386やamd64なマシンでLinuxでpoweroffコマンドを実行すると最後に処理されるのはこの辺のコードです。

https://github.com/torvalds/linux/blob/94f0b2d4a1d0c52035aef425da5e022bd2cb1c71/drivers/acpi/sleep.c#L1027

FreeBSDではこの辺です。

https://cgit.freebsd.org/src/tree/sys/dev/acpica/acpi.c#n2188

同じような処理をしてますね。

FreeBSDでWOLするとpoweroffせずrebootするケースがあり調べています。FreeBSDでpoweroffするとWOLできなくなるケースもあります、この辺になにかおまじないが必要なのでしょうか？

FreeBSDのbgeのWOL対応でWOL後にpoweroffするとrebootしてしまうのでメインライン入れられてないのですが、自分のところのalcでも同じことがおきます。おそらくドライバーの問題ではないような気がしています。
[Ruby on Rails] renderとredirect_toの違い

初めに...学習期間1ヶ月未満の超絶初心者です。
不明点等を整理するために記述しており、
誤り、勘違い、理解不足等　多々あるかと思います。


<h1>render と　redirect toの違い

一言で言うと、アクションを通るか通らないか。


```
　　　def new
   @post_image=PostImage.new
　　　end

  def create
    @post_image = PostImage.new(post_image_params)
    @post_image.user_id = current_user.id
    if @post_image.save
      redirect_to post_images_path
    else
      render :new
    end
```

上記の記述の場合。
今、def createで@post_imageさんは、投稿された情報を持っている状態。
if文があるので、その投稿情報が保存されたらredirect toしますが、
保存されなかった場合、render:newとあるので、
とりあえず@post_imageさんは今の情報を持ったままnewのviewページに渡します。

@post_imageさん：「newのviewページさん、これが@post_imageの持ってる情報です。表示お願いします...」



<h1>redirect toにしたらどうなるか。

renderとなってる箇所をredirect_toにするとどうなるのか。
一度、上の方に記載してある　def newを通過しないといけなくなります。
def createで投稿された情報を持っている@post_imageさん。
しかし、newアクションで@post_image=PostImage.newと記述があるため、
今持ってる情報はポイっと手放し、空の箱を手渡されます。
そして、newのviewページさんに渡します。


<h1>何か不都合があるのか。。

renderを使うことで、保存はされてない投稿情報が、viewに渡せるので、
このようにエラー文と、中途半端に打った情報が、表示されます。
redirect toにしてしまうと、エラー文も表示されないのではないかと思う。

![スクリーンショット 2021-06-16 15.43.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/baaf9761-a8ff-2f1f-8205-75a075ba64f9.png)
【論文紹介】LOLLio: exploring taste as playful modality

#論文紹介
論文：LOLLio: exploring taste as playful modality
著者：Martin Murer, Ilhan Aslan, Manfred Tscheligi
https://dl.acm.org/doi/pdf/10.1145/2460625.2460675

#どんなもの
　味覚を動的に変化させる触覚入力デバイスとして機能するインタラクティブなロリポップ(ペロペロキャンディ)デバイスLOLLioの開発。LOLLioは甘いロリポップを用いて、持ち手の部分からキャンディの出口に少量の酸味の液体を送り込むことで、甘味と酸味を提示する。実験の結果、甘味と酸味の相互作用によって、様々なタイプの味覚ゲームに適していることがわかった。このことから、LOLLioを使って、斬新で遊び心のあるゲーム体験を生み出すこができると示唆した。

#先行研究と比較してすごいところ
　視覚、聴覚、触覚におけるインタラクション・モダリティの観点からはよく研究されているが、味覚と嗅覚における研究は少ない。この理由の1つとして味覚を使った経験は長期間ではないことがある。ペロペロキャンディは長く続く味覚体験を提供するということから、LOLLioを開発した。

#技術や手法のキモ
　LOLLioは甘味と酸味に焦点を当てた。一般的な甘いペロペロキャンディとコンピュータ制御による酸っぱい液体の供給を組み合わせた。甘いロリポップを用いて、持ち手の部分からキャンディの出口に少量の酸味のある液体(薄めたクエン酸)が送り込まれる。高濃度の酸味料を使用し、流す量を変化することで、酸味と甘味の間の異なる味を提示した。

#検証方法
　非公式なテストの結果
　→酸味と甘味の間に複数の識別可能な味を提供できた。ゲーム内では、報酬や罰としての味や隠された情報としての味、味に対するユーザの反応と組み合わせた味といったように使うことができる。


#議論
　酸味と甘味以外の味を提示することはできないのか。


#気になった論文
　Playful Taste Interaction
【kotlin】オブジェクト式

#■オブジェクト式とは
Android開発では再利用しないクラスがよくある。
そういった時に便利なのがオブジェクト式機能
書き方

``` kotlin
object{クラス本体}
```

クラスの継承やインターフェースの実装も可能

``` kotlin
object: 親クラス or インターフェイス{クラス本体}
```

####■使い方
リスナクラスで使ったりする。
setOnClickListenerメソッドの中でobject式を利用
View.OnClickListenerインターフェイスを実装している。

▼何故object式を利用するか？
決められたボタンを押した時の処理意外使わないから

``` kotlin
btn.setOnClickListener(object: View.OnClickListener {
  override fun onClick(view: View) {
    ボタンがクリックされた時の処理
   }
})
```

▼SAMインターフェイスとは
View.OnClickListenerインターフェイスのように抽象メソッドを一つしか持たないもの。
抽象メソッドを一つしか持たないインターフェイスをSAMインターフェイスと呼ぶ。

#■SAM変換でもっとシンプルに！
オブジェクト式で実装するインターフェイスがSAMインターフェイスの場合
ラムダ式で置き換えて省略してコードをシンプルにできる。

■省略コード
object
SAMインターフェイス: setOnClickListenerで使うSAMインターフェイスは決まっている。推論できる。
override fun onClickメソッド: SAMインターフェイスなので使うメソッドも推論できる。

``` kotlin
btn.setOnClickListener({ view: View -> 処理})
```

#■ラムダ式の省略記法を使いもっともっとシンプルに！！！！

▼ラムダ式の省略記法
●引数の型があきらかなら省略可能
●引数を利用しないなら引数そのものを省略可能
●ラムダ式を囲む()を省略可能

``` kotlin
btn.setOnClickListener{処理}
```

よくみる書き方！
これはオブジェクト式を使いSAM変換しラムダ式でここまで省略した姿だったと言う事です！！！！！
【FileMaker】タイムスタンプフィールドから日付と時間を取得する

[Claris社のヘルプ](https://help.claris.com/ja/pro-help/content/index.html)は広く公開されていていつでもどこでも確認できるのがとても素晴らしいのですが、たまに自分の頭がついていかない時があるので、理解している範囲で備忘録として残しておきます。

今回のお題は、タイトルにある通り、タイムスタンプフィールドから日付と時間を取得する場合の関数です。
え？
あれしかないじゃん？
あれしかないですよね。
ただ、ヘルプを見ると、「テキスト」が引数になっているので一瞬「え、タイムスタンプはダメなの？」とびびります。

こちらに[GetAsDate(テキスト)](https://help.claris.com/ja/pro-help/content/getasdate.html)のヘルプを一部引用します。
![スクリーンショット 2021-06-16 15.11.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/035c29f0-266f-27e8-a6ec-67ce30f8b058.png)
「システムの日付と同じ書式のテキスト」とあるので、同じ書式であれば問題ないと理解できます。
実際、ヘルプのサンプルにも、タイムスタンプフィールドの例を出しています。
でも、明確にタイムスタンプフィールドOKとは書いていないので、恐る恐るテストしたくなります。

実際テキストの引数部分にタイムスタンプフィールドを指定しても正常に処理されるので、「そうか、タイムスタンプフィールドは、日時をある形式に従った形のテキストとして保存されているんだな」と理解が深まります。
そうなんだ。。。

じゃ、「テキスト」だけじゃなくて「タイムスタンプ」とも書いてくれよ。

と壺の中で叫びたくなりますが、ここで一度動きを確認してみなさんと理解を共有しておこうと思います。

# 日付を取得する
GetAsDateの引数に、タイムスタンプを指定します。
![スクリーンショット 2021-06-16 15.16.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/6c8ee856-471a-0e06-7582-230024e7e24b.png)

結果、日付が取得できます。
![スクリーンショット 2021-06-16 15.17.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/6eb4895e-dac6-3aa1-c1c9-c83298bb22e9.png)

# 時間を取得する
[GetAsTime](https://help.claris.com/ja/pro-help/content/getastime.html)の引数に、タイムスタンプを指定します。
![スクリーンショット 2021-06-16 15.16.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/2a272370-2683-5821-8cc1-a3e0ca3cd360.png)

結果、時間が取得できます。
![スクリーンショット 2021-06-16 15.17.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/65ffbbf0-7c94-dd84-f391-a43f9c1ad406.png)

# スラッシュ抜きで日付を取得する
よく、出力するファイル名に日付としてYYYYMMDDのような仕様で付けたい場合があります。
![スクリーンショット 2021-06-16 15.16.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/81ea4062-45e1-288c-692b-33f0516c8f14.png)

ちゃんと、ゼロ埋めもされてます。
![スクリーンショット 2021-06-16 15.17.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/39ca92c2-d321-ed64-0775-2a15ec0c786b.png)

ということで、今回は単純なことだけど、ヘルプの記載に惑わされそうな部分をピックアップしてみました。
Laravel でのカスタムバリデーションルールのまとめ

#初めに
この記事は執筆時点での最新版である laravel8.x と LTS である laravel6.x を前提に記述しています。

前回作成したバリデーションの基本的な構文の[記事](https://qiita.com/tf_okrt/items/ac4b3a297fc15a80da5e)でカスタムルールについて少し触れたので、今回は実際の記載方法を紹介したいと思います。

# 手法
カスタムバリデーションルールの実装方法は主に以下の 3 つとなる

1. クロージャの使用
2. Rule オブジェクトの使用
3. Validator ファサードの拡張

# 1.クロージャの使用
用途：その場限定のルール
バージョン対応：laravel8.x, laravel6.x

## 構文

```php
Validator::make($request->all(),
    [
        (パラメータ名) => [
            '(ルール1)',
            '(ルール2)',
            function ($attribute, $value, $fail) {
                if (判定したい条件式) {
                    $fail('エラーメッセージ');
                }
            },
        ],
    ],[]
)->validate();
```

## 引数の説明
`$attribute`：パラメータ名
`$value`：パラメータの値
`$attribute`：失敗時の処理（エラーメッセージの適用）

# 2.Rule オブジェクトの使用
用途：プロジェクト内で共有したいルール
バージョン対応：laravel8.x, laravel6.x

## 生成方法
以下のコマンドを実行

```
php artisan make:rule (クラス名)
```

生成先：app/Rules


## クラスファイルの構文

```php
<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class SampleRule implements Rule
{
    public function passes($attribute, $value)
    {
        return (条件式);
    }

    public function message()
    {
        return '(エラーメッセージ)';
    }
}
```

## 関数の説明
`passes`：バリデーションが成功する条件式を返す関数
`message`：バリデーションエラーメッセージを返す関数

## 使用する際の構文

```php
use App\Rules\SampleRule

(中略)

Validator::make($request->all(),
    [
        (パラメータ名) => [
            '(ルール1)',
            '(ルール2)',
            new SampleRule,
        ],
    ],[]
)->validate();
```

# 3.Validator ファサードの拡張
用途：プロジェクト内で共有したいルール
バージョン対応：laravel6.x

## 拡張方法
AppServiceProvider などのサービスプロバイダ内で登録

```php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

class AppServiceProvider extends ServiceProvider
{
    (中略)

    public function boot()
    {
        Validator::extend(
            '(ルール名)',
            function ($attribute, $value, $parameters, $validator) {
                return (条件式);
            }
        );
    }
}
```

## クロージャの引数の説明
`$attribute`：パラメータ名
`$value`：パラメータの値
`$parameters`：ルールに渡した引数（`(ルール名):foo,bar`の`foo,bar`）
`$validator`：Validator インスタンス

## エラーメッセージの設定
以下のどちらかの方法で指定
A：`Validator::make()`の第3引数のカスタムエラーメッセージ配列内で指定
B：バリデーション言語ファイルで指定

## ルールクロージャの単一ファイル管理
config 等で

```php
[(ルール名) => (クロージャ), ...]
```

という形でルールを集約し、拡張側の実装を

```php
$rules = config('custom_rules');
foreach($rules as $key => $closure) {
    Validator::extend($key, $closure);
}
```

と実装することも可能

# 使い分け
|手法|実装箇所|利点|欠点|
|---|---|---|---|
|クロージャ|ルールの使用箇所|即席での実装|実装の散逸|
|Rule オブジェクト|クラスファイル内|単一の実装箇所による変更の容易性|使用箇所でのインポート宣言が必要|
|Validator の拡張|サービスプロバイダ内|単一の実装箇所による変更の容易性<br>ルールクロージャの集約が可能|エラーメッセージの設定との分離|
【UiPath】設定ファイルで処理ブロックを制御する

# はじめに

この投稿は、RPAツール「UiPath」での **設定ファイルの使用パターン** についての記事です。

※ 良くあるパターンの紹介なので、御存知の方は復習程度にお読みください。

# 処理内容をスキップしたい時がある

テストや実運用フェーズになると「**途中から処理したい**」時や「**途中で処理を止めたい**」という要望が出ることがあります。例えば、以下の流れで処理するフローが合ったとします。

```
　1：データ取得
　2：データ加工
　3：データアップロード
　4：実行結果のメール送信
```

この時、以下のような要望が出た　とします。

 - 「1：データ取得」をスキップしたい（データ取得は終わってるので）
 - 「4：実行結果のメール送信」はやらなくていい（実行結果は横で見てれば分かるから）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/c7f8b972-c7bd-6d5c-47da-9f8113e3c98d.png)


コードを書き換えて、処理を削っても良いのですが、こういう時は、「**設定ファイルで実行制御できる**」ように実装しておくと便利です。以下のいざうれかで実現できます。

```
方法1）設定ファイルで「実行開始／終了」ステップを指定する
方法2）設定ファイルで「処理毎の実行フラグ」を指定する
方法3）設定ファイルで「実行する処理名」を指定する
```

以下で説明します。

# 方法1）「実行開始／終了」ステップを指定する

設定ファイルに以下のような項目を用意します。（実行開始ステップ、実行終了ステップ）

| 設定項目名 | 値 |
|:-|:-|
| 処理開始番号 | 2 |
| 処理終了番号 | 3 |

フロー側では以下のように記述します。
![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/d39a972a-232a-d450-f1f1-e46e94d76969.png)


こうすることで、設定ファイルで「実行開始／終了」ステップを指定する事ができます。
この方法のデメリットは以下があります。

- 処理開始／終了番号の「数字」が何を指すか分かりにくい（3って何の処理？）
- 間に処理追加なら見直しが必要（番号をズラしていくのが面倒）
- 間の処理をスキップすることが出来ない（例：1は実施、2はスキップ、3は実施）

# 方法2）設定ファイルで「処理毎の実行フラグ」を指定する

設定ファイルに以下のような項目を用意します。（処理毎の実行有無を示すフラグ）

| 設定項目名 | 値 |
|:-|:-|
|データ取得を実行する|YES|
|データ加工を実行する|YES|
|データアップロードを実行する|YES|
|実行結果のメール送信を実行する|YES|

フロー側では以下のように記述します。
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/73002663-eff5-8c80-1bce-e28a96944c58.png)


こうすることで、設定ファイルで各ブロック単位で処理するしないをコントロールできます。
この方法のデメリットは以下があります。

- 処理ブロックが増えるたびに設定項目が増える

# 方法3）「実行する処理名」ステップを指定する

設定ファイルに以下のような項目を用意します。（実行処理名）

| 設定項目名 | 値 |
|:-|:-|
| 実行処理名 | データ加工,データアップロード |

フロー側では以下のように記述します。

![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/09b099d6-81b3-887f-e976-21d659eb448a.png)
こうすることで、設定ファイルで処理ブロック単位の「処理する／しない」をコントロールできます。
この方法のデメリットは以下があります。

- 処理ブロックの文字を間違えてはいけない

# 終わりに

いかがでしたでしょうか。

個人的には　`「方法2）設定ファイルで「処理毎の実行フラグ」を指定する」`で書いておいて、
項目が増えてきたら　`「方法3）「実行する処理名」ステップを指定する」` に移行していきます。
実装例として役立てば幸いです。

この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
Rails 配列からnil,空文字を取り除く 配列の結合

###配列からnil,空文字を取り除きたい時

```
.reject(&:blank?)
```


###配列を結合したい時

```
a = ["apple", "banana", "orange"]
b = ["grape", "apple", "orange"]
a | b
=> ["apple", "banana", "orange", "grape"]
```
###+を使った場合

```
a = ["apple", "banana", "orange"]
b = ["grape", "apple", "orange"]
a + b
=> ["apple", "banana", "orange", "grape", "apple", "orange"]
```
AIはどんなことに使われているかを知るサイト AIsmiley, e.g.

AIはどのようなことに使われているかを知ることができるWEBサイトを2つ教わったので、その紹介と感想を書いておきます。

# 1 AIsmiley
URL : https://ai-products.net/
人工知能を搭載した製品・サービスの比較一覧、導入活用事例、資料請求ができるAIポータルメディア

気になったAI製品があれば、すぐに資料請求ができるAIのカタログサイトのような感じですね。
気になった記事をいくつかピックアップします。

## 1.1 AI画像判定サービス 「MMEye」
URL : https://ai-products.net/product/mmeye/
AIが画像を学習し、異常検知、物体検知、分類を自動化することで、食品製造業などで、不良品の検知などに使うことができるというサービスです。
サンプル画像では、クラッカーの選別の画像が載っていましたが、たしかにクラッカーのような平たい物だと比較的簡単に検品できるのではないかと思いました。
立体的なもの、例えばりんごのようなものだと、検品するプログラムも、それを撮影するカメラも、かなり複雑になりそうだなということが現時点の僕の知識でも想像できます。


## 1.2 自然言語AI・QA支援システム 「ふれあいコンシェルジュ」
URL : https://ai-products.net/product/hureai/
企業のベテランしか知らないような知識を新入社員にも共有できるように、すべてAIに学習させて、誰でもAIに質問すれば、過去の知見について教えてくれるようなサービスです。
言葉の揺らぎ（送り仮名の違い、固有名詞の違いなど）を理解して回答してくれるのは結構頼もしいですね。
会社のクラウドの中にデータを入れていても、探そうと思った時には、どこにあるのかもどうやって探せばいいかもわからない状況になりがちですので、使い方次第では便利だなと思いました。
また、AIで勝手に言葉の揺らぎを学習していくそうなので、回答精度があがり、そのうち本当にベテラン社員が不要になってしまうかも…。

# 2 e.g. 
URL : https://ledge-eg.com/
国内最大級の事例数をもつ、AI活用事例の検索プラットフォーム

産業、用途、技術で絞ることができます。
サービスを利用するには会員登録が必要です。

## 2.1 風速データと気象観測データをAIに学習させ局所地域での風速予測を実現
URL : https://ledge-eg.com/cases/windvelocity
建設産業で検索してみたら5件ヒットしました。そのうちの一つです。
風速系データと1kmメッシュの気象観測データを学習させることで、局所地域での5時間後までの風速予測を実現しています。
建設業界に少しいたからわかるのですが、強風は工事を中断するきっかけにもなるやっかいなものです。
正確に予測できれば、工事のスケジュールが組みやすくなるので、便利だと思います。

## 2.2 手作業で行なっていた単純作業にAIを導入して年間約2万5700時間の工数削減に成功
URL : https://ledge-eg.com/cases/openhouse
物件案内図の帯の差し替え作業を自動化するAIを自社開発し、作業工数を大幅に削減
物件案内図の、不動産会社名、連絡先、免許番号など必要な情報が記された“帯”の内容を自社の内容に差し替える作業を自動化するAIを開発。
こういった単純作業の差し替えを全自動にするというのは夢がありますね。
年間2万5700時間の削減とありますから、時給1000円だとしても2570万円の節約ができたわけですね。素晴らしい。

# 3 まとめ
AIは意外と我々の生活に溶け込んでいるんですね。
もっと色んなことが自動化されていくといいですね。
AIエンジニアの仕事が増えると思うので。笑
typeofの概要メモ[JavaScript]

MDNで調べたことを備忘録としてメモします。
現在はMDNからの引用が中心ですが、今後、使ってみて便利だと感じたケースなども追記していきたいと思っています。

>typeof 演算子は、未評価のオペランドの型を示す文字列を返します。

```JavaScript:example.js
console.log(typeof 42);
// expected output: "number"

console.log(typeof 'blubber');
// expected output: "string"

console.log(typeof true);
// expected output: "boolean"

console.log(typeof undeclaredVariable);
// expected output: "undefined"
```

##構文
>typeof 演算子の後に、オペランドを続けて書きます。

```
typeof operand
typeof(operand)
```

##typeof が返す事が出来る値 (文字列) の一覧表

| 型 |返値 | 
|:-----------|------------:|
|Undefined     |"undefined"| 
| Null   |"object"| 
|真偽値     |"boolean"|
|数値      |"number"| 
|BigInt (ECMAScript 2020 の新機能)     |"bigint"| 
| 文字列 |"string"| 
|シンボル (ECMAScript 2015 の新機能) |"symbol"| 
|Function オブジェクト (implements [[Call]] in ECMA-262 terms) |"function"| 
| その他のオブジェクト |"object"| 

※Nullの場合も"object"を返す

##参考
[typeof - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof)
TreasureDataをTableauで可視化する

普段は、BigQueryを使ってデータを可視化することが多いのですが、TreasureDataでも可視化したい！ということになったのでそちらを試してみました。
ちょっとハマった点なども記載したいと思います。

ハマった点は「Prestoにアクセスした後にスキーマが出てこなくて、接続できてないんじゃないの？？？？？」となったと頃が一番はまりました。
BigQueryなどではDataSetを選べば、基本的にDataSet名、テーブル名は出てくるので、なんででてこないんじゃぁぁぁとちゃぶ台投げました

#Prestoを使えるようにする
TreasureDataは、Engineとして、PrestoとHiveが利用できますが、PrestoEngineをつかってTableauからつなごうと思います

MacOSでの設定を記載します

インストールは、[こちら](https://www.tableau.com/support/drivers "Install Driver")　より、**Presto**を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/a7724abc-f453-e3af-d192-db3ec66af49a.png)

Simba Presto 1.1.pkgをダウンロードして、インストールします。

#Tableauで接続設定
TableauDesktopを立ち上げ、サーバーへ→その他...→Prestoを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/4bfd0291-bca7-92f6-6f3d-41e43bad38d9.png)

| 項目 | 設定 | 備考 |
|:-----------|:------------|:------------:|
| サーバー     | api-presto.treasuredata.co.jp        | 利用のTreasureDataのドメインによる api-presto.treasuredata.com も         | 
| ポート | 443 ||
| カタログ　| td-presto||
|スキーマ|（オプション）|※そのまま|
| 認証 | ユーザ名 ||
| ユーザ名 | TreasureDataのMaster APIKey | ※1 |
| SSLが必須(L) | チェックする ||

## APIキー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/e58ee603-1943-5ae9-8b14-176988bb6a83.png)

My Settingから、API Keys　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/05d2033c-bdcb-0395-98d4-951f6a2f9ae7.png)

Access Typeが、Master KeyのAPI Keyを取得します

#Tableauで接続
サインインすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/397a6c06-072f-b819-7e43-976dadea4018.png)
スキーマを選択しても、候補が出てこない・・・・
私はここでハマりました　orz

スキーマ名とテーブル名は、検索しないと出てこないのです・・・・orz
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/ba53ff9d-8f4c-553a-7761-7d766c64c07e.png)

それぞれ検索（正確、部分一致、前方一致）して、テーブル候補を出してから、テーブルをドラッグします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140981/c855a547-8c43-07f9-f7c7-fd5465c2776c.png)

ここまでできたら、後は普通に分析をしたりダッシュボードを作ったりするのでOKです
AWS Backupの画面操作で状況確認

画面キャプチャは 2021/06/16 のもの

# 前提情報

画面で言うと、まず"ダッシュボード"はあんまり見なくていいです。
"バックアップボルト","バックアッププラン","保護されたリソース"は普通に使います。
ジョブの状態を見るときは、"ジョブ"と"クロスアカウントモニタリング"を使います。今回はここ。
"設定"は一回使ったらあとはほとんど見ない。

# ジョブ

メニューの「ジョブ」は、バックアップジョブなど各種ジョブのステータスを確認できます。バックアップはいつ実行したか？いつ終わったか？成功したか？とかですね。
ジョブは以下の3種類あります。

* バックアップジョブ：バックアップのジョブ
* ジョブを復元：リストアのジョブ
* コピージョブ：別リージョンや同一リージョンへのコピー、他のAWSアカウントの別リージョンや同一リージョンへのコピー

以下は、バックアップジョブの履歴です。

![スクリーンショット 0003-06-16 14.11.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/ac0bae5a-f026-c9ce-e75f-85a1f28ed069.png)

#### バックアップジョブ

* ジョブID, ステータス でフィルタできます

上記画面の、一番上のバックアップジョブIDをクリックします。

![スクリーンショット 0003-06-16 14.18.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/13bd9d32-f06c-be05-d9d9-ea9bc69e8c8b.png)

* 実行中のジョブであれば、この画面で右上の[停止]でジョブを停止できます。

"復旧ポイントARN"をクリックします。

![スクリーンショット 0003-06-16 14.19.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/957627ad-cc7e-68b7-e5e3-ab9e8df64eae.png)

このバックアップジョブで作成された復旧ポイントに飛びます。

* コピーできます。右上の[コピー]からバックアップしたスナップショットを別リージョンや別ボルトや別AWSアカウントにコピーできます
* 復元できます。右上の[復元]からバックアップを復元できます
* 削除できます。右上の[削除]でこの復旧ポイントやバックアップを削除します
* 保持期間変更。右下の[編集する]でスナップショットの保持期間を変更できます

![スクリーンショット 0003-06-16 14.22.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/e847eb46-6b5c-818d-b7be-2f526bf4aff7.png)

#### ジョブを復元

リストアのジョブ(復元ジョブ)の履歴です。

![スクリーンショット 0003-06-16 14.26.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/8b8423ba-a4b0-cf8c-09c3-e9a88d816231.png)

* ジョブID, ステータス でフィルタできます

上記画面の、一番上の復元ジョブIDをクリックします。

![スクリーンショット 0003-06-16 14.27.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/2adc4950-95b0-8af1-7ecc-65f1dc663802.png)

* 復元ジョブの内容が確認できます。
* 復元に使った復旧ポイント、ステータス、復元されたリソースID、リソースタイプ、実施日、完了日、サイズなど

![スクリーンショット 0003-06-16 14.29.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/817fccb4-a311-e920-099c-466d1006bec9.png)

#### コピージョブ

コピージョブの履歴

![スクリーンショット 0003-06-16 14.31.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/8890b1fd-5413-a6d7-b4b3-880e75f26a1b.png)

* 送信先, ジョブID, ステータス でフィルタできます

上記画面の、一番上のコピージョブIDをクリックします。

![スクリーンショット 0003-06-16 14.31.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/150068f4-c118-360b-2f49-b1e2c6a63505.png)

* コピージョブの内容が確認できます。
* コピーに使った復旧ポイント、ステータス、コピーされたリソースID、リソースタイプ、実施日、完了日、サイズなど

以下だと東京リージョンのtmp-vaultボルトから大阪リージョンのDefaultボルトにコピーしています。

取得したバックアップを東京から大阪にコピー

![スクリーンショット 0003-06-16 14.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/debd1d6b-348d-5bc3-a976-b2b466a07edc.png)

# クロスアカウントモニタリング

メニューの「クロスアカウントモニタリング」は、複数のアカウントを横断して、上記のジョブと同じ内容を確認できます。

* Organizationの親で"クロスアカウントモニタリング"を有効にしている必要があります

![スクリーンショット 0003-06-16 14.38.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/b88ff032-f84d-c9c9-2675-370faeec35f0.png)

* アカウント, ジョブID, ステータス でフィルタできます

![スクリーンショット 0003-06-16 14.39.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/a9a558ba-1efc-c027-1aa2-1f9de065e161.png)

## 参考

AWS Backupの薄い教科書
https://qiita.com/pioho07/items/68ccbc7b974b1466e7a6
ゼロからのOS自作入門 第２章

# ゼロからのOS自作入門 第２章

いくつか独自に進めた部分のメモ

## MikanLoaderPkgのシンボリックリンク
EDK2でEFIアプリをビルドするにはEDK2のWORKSPACE内にそのディレクトリがある必要があるために、本ではWORKSPACE内にシンボリックリンクを作成して、MikanLoaderPkgをその中に置くように見せかせている。

以下を少し読んだ感じだと、`PACKAGES_PATH`環境変数があればその中を探してくれるということなので、それを使ってみた。
https://edk2-docs.gitbook.io/edk-ii-build-specification/4_edk_ii_build_process_overview/41_edk_ii_build_system

例えば、`~/MikanOS/MikanLoaderPkg`にMain.cやdec,infファイル等をおいた場合、

```
$ export PACKAGES_PATH=~/MikanOS
```
としておけばシンボリックリンクは必要ない。


## EDK2のバージョン
EDK2のリポジトリからファイルを`git clone https://github.com/tianocore/edk2`で持ってくるとmasterがチェックアウトされている。
何人かが指摘しているが、このままだとビルドがうまく行かない。
やることは大きく２つ。EDK2のディレクトリ内で以下のコマンドで特定のバージョンのチェックアウト及びSubmouleの取得を行う。

```
$ git checkout edk2-stable202011
$ git submodule init
```

## BaseToolsのビルド
これがどこにも書かれていなかったので、もしかすると僕が見逃しているか、完全に本にそって手順を進めていないのでちょっと環境が違うとかかもしれないが、EDK2のリポジトリ内のBaseToolsを先にビルドする必要があった。EDK2のディレクトリ内で

```
$ make -C BaseTools
```
なお筆者のArch Linuxの環境(gcc version 11)ではWarningがでて、それがエラーとなってコンパイルエラーになってしまったので、以下のファイルから`-Wall -Werror`を無理やり削除してコンパイルした。

```Makefile:BaseTools/Source/C/Makefiles/header.makefile
 94 BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \
 95 # -fno-delete-null-pointer-checks -Wall -Werror \
 96 -fno-delete-null-pointer-checks \
 97 -Wno-deprecated-declarations -Wno-stringop-truncation -Wno-restrict \
 98 -Wno-unused-result -nostdlib -g
```
コンパイル環境に応じて`ifeq/endif`で囲まれているので自分の環境の場所を見つけて削除。(上の例では95行をコメントアウトして、96行目に`-Wall -Werror`を削除したものを追加)

## nasmのインストール
本に書いてある開発環境を無視してやっているので、nasmがなくてビルドに失敗した。Arch Linuxを使っているので以下でインストール
```
$ sudo pacman -S nasm
```

ほかは本に従って記述していくことでLoader.efiが出来上がりました。
Java PDFページの向きを判定　

<p><strong>今日はSpire.PDF for Javaという無料のライブラリを活用して、PDFページの向きを判定する方法を紹介します。</strong></p>
<h4><strong>下準備</strong></h4>
<p><strong>1.E-iceblueの公式サイトからF<a href="https://www.e-iceblue.com/Download/pdf-for-java.html">ree Spire.PDF for Java</a>無料版をダウンロードしてください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210616/20210616144244.png" alt="f:id:lendoris:20210616144244p:plain" width="554" height="188" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire.PDF.jarを参照に追加してください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210616/20210616144252.png" alt="f:id:lendoris:20210616144252p:plain" width="268" height="108" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
```JAVA
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;

public class DetectPageOrientation {
    public static void main(String[] args){
        //PDFをロードします。
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("Fields.pdf");

        //初めのページを取得します。
        PdfPageBase page = pdf.getPages().get(0);

        // ページの幅と高さを比較します。
        if (page.getSize().getWidth()> page.getSize().getHeight()){
            System.out.println("ページは横向きです");
        }
        else{
            System.out.println("ページは縦向きです");
        }
    }
}
```
<h4><strong>実行結果</strong></h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210616/20210616144909.png" alt="f:id:lendoris:20210616144909p:plain" width="290" height="183" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p> </p>
Laravelで特定のレコードを除外して取得する

# 特定のレコードを除外して取得する
詳細ページに移行して、その詳細ページを除いた他のページを候補として出したいなど、
それ以外の所得したい場合があると思います。
今回はその方法をアウトプットしていきます。

## WhereNotInを利用する場合
第一引数でカラムを指定
第二引数で除外したいレコードのid配列を入れる
第三引数でstrictを厳格化

````php:
Test::whereNotIn('id', [$testId], true);
````

## filter
filter()に関してはドキュメントを読んでみましょう
https://readouble.com/laravel/5.8/ja/collections.html#method-filter
>filterメソッドは指定したコールバックでコレクションをフィルタリングします。テストでtrueを返したアイテムだけが残ります。

````php:
Test::filter(fn (Test $test) => $test->id !== $testId);
````
これで取得できてしまいます
Java  PDFで画像を追加

<p><strong>今日はSpire.PDF for Javaという無料のライブラリを活用して、PDFで画像を追加する方法を紹介します。</strong></p>
<h4><strong>下準備</strong></h4>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/pdf-for-java.html">Free Spire.PDF for Java</a>無料版をダウンロードしてください。</strong></p>
<p><strong> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210616/20210616144244.png" alt="f:id:lendoris:20210616144244p:plain" width="554" height="188" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></strong></p>
<p><strong>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire.PDF.jarを参照に追加してください。</strong></p>
<p><strong> </strong><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210616/20210616144252.png" alt="f:id:lendoris:20210616144252p:plain" width="268" height="108" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
```JAVA
import com.spire.pdf.*;
import com.spire.pdf.graphics.*;

public class AddImage {
    public static void main(String[] args) {
        //ファイルを作成します。
        PdfDocument pdf = new PdfDocument();

        //ページを追加します。
        PdfPageBase page = pdf.getPages().add();

        //写真をロードし、高さと幅を取得します。
        PdfImage image = PdfImage.fromFile("fj.png");
        int width = image.getWidth()/2;
        int height = image.getHeight()/2;

        //PDFに写真を追加します
        page.getCanvas().drawImage(image,50,50,width, height);

        //保存します。
        pdf.saveToFile("result.pdf");
        pdf.dispose();
    }
}
```
<h4><strong>実行結果</strong></h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210616/20210616144346.png" alt="f:id:lendoris:20210616144346p:plain" width="554" height="424" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p> </p>
【初心者】MAMPのphpMyAdminでLaravelのDBのmigrateができない時に試した事【解決済み】

## はじめに
当記事の内容は表題のとおりです。
ローカル(MAMP)でLaravelアプリケーションを立ち上げた時、マイグレーション(migration)ができなかったのでその対処を記録します。
また、私は初学者なので誤っている点がありましたらご指摘いただけますと幸いです。

## 開発環境
macOS 11.2.2
MAMP(Apache/PHP version:7.4.12)
PHP 8.0.6
Laravel Framework 8.46.0


## 起こった事象
Laravelにて新規アプリケーションを立ち上げ</br>
↓
モデルを作成
↓
phpMyAdmin上で使用するDBを作成
↓
.envファイルを編集
↓
マイグレーション実行
↓
下記のエラー

```shell-session
% php artisan migrate

 Illuminate\Database\QueryException 

  SQLSTATE[HY000] [1049] Unknown database 'phpMyAdminで作成したDB名' (SQL: select * from information_schema.tables where table_schema = mydbs and table_name = migrations and table_type = 'BASE TABLE')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:692
    688▕         // If an exception occurs when attempting to run a query, we'll format the error
    689▕         // message to include the bindings with SQL, which will make this exception a
    690▕         // lot more helpful to the developer instead of just the database's errors.
    691▕         catch (Exception $e) {
  ➜ 692▕             throw new QueryException(
    693▕                 $query, $this->prepareBindings($bindings), $e
    694▕             );
    695▕         }
    696▕ 

      +33 vendor frames 
  34  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
```


## 行った対処
### `.env`の内容を修正

マニュアルの手順どおりの記載だとエラーが発生したため下記のように変更しました。

```php:.env
変更前(エラーになる状態)
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=phpMyAdminで作成したDB名
DB_USERNAME=root
# DB_PASSWORD=

↓ 下記に変更

変更後(migrationできる)
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=8889
DB_DATABASE=phpMyAdminで作成したDB名
DB_USERNAME=root
DB_PASSWORD=root
```

記載を変更した箇所についてはローカルのMAMPのトップ画面(http://localhost:8888/MAMP/) を参照しました。
(`DB_HOST=127.0.0.1`の`127.0.0.1`はlocalhostを指す)
![MAMP_top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684845/5e2d14a1-d4e5-79f9-4aeb-c6b8a011148f.png)
</br>

### マイグレーションを再度実行

```shell
# マイグレーション前にキャッシュをクリア
% php artisan config:cache

Configuration cache cleared!
Configuration cached successfully!

# マイグレーションを実行
% php artisan migrate

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (75.91ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (63.72ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (68.31ms)
Migrating: 2021_06_16_021409_create_articles_table
Migrated:  2021_06_16_021409_create_articles_table (32.20ms)
```
↑のように今度はマイグレーションが正しく実行できました。

## おわりに
同じような環境でつまずいている方のヒントになれば幸いです。
間違っている点がありましたらお知らせください。
WindowsコンテナでMemory limit指定時に「The requested resource is in use.」で起動できない問題への対処方法

# 概要

WindowsイメージでMemory limit（-mオプション）を指定してコンテナを生成すると以下のエラーが発生することがあります。

```
docker run --rm -it -m 4G mcr.microsoft.com/windows:20H2 cmd
docker: Error response from daemon: hcsshim::CreateComputeSystem 58b22e8bf229bb443b5d5765e9523b4f77c10b4ccdfa0867877f8de7cf189532: The requested resource is in use.
```

`-m 4G` を指定することで、Windowsコンテナへメモリ4Gを割り当ててコンテナを生成できますが、エラーが発生する場合と発生しない場合があり、エラーの原因が不明でした。事例などを調べても根本原因を突き止めることができませんでした。

一方、 `-m 4G` を指定しない場合は正常にWindowsコンテナが生成できます。
ただし、この場合はメモリはデフォルトの1Gのみの割り当てとなります。

```
Microsoft Windows [Version 10.0.19042.985]
(c) Microsoft Corporation. All rights reserved.

C:\>systeminfo

...(略)...
Total Physical Memory:     1,023 MB
Available Physical Memory: 636 MB
Virtual Memory: Max Size:  2,751 MB
Virtual Memory: Available: 2,290 MB
Virtual Memory: In Use:    461 MB
...(略)...
```

Dockerの再起動やOSの再起動など、様々なことを試しても改善しませんでしたが、対処方法が見つかりましたので本記事にてご紹介します。

# 前提条件

* Windows 10 Pro 20H2 で Docker を利用している
* Docker Desktop for Windows 3.4.0 を利用している
* Windows containers モードを利用している
* mcr.microsoft.com/windows:20H2 イメージを利用している

# 対処方法

1. Windowsのスタートメニューで `hyper-v` と入力して `Hyper-V マネージャー` 画面を起動します。
1. 操作メニューから `Hyper-V の設定...` を開きます。
1. `仮想マシンに物理NUMAノードをまたがるメモリを割り当てる` のチェックを解除してOKボタンで確定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278145/055cfe92-5871-c4a7-2c9e-42bccfc816a2.png)
1. Windowsのスタートメニューで `service` と入力して `サービス` 画面を起動します。
1. 以下のサービスを再起動します。
   * Hyper-V Virtual Machine Management
   * Hyper-V ホスト コンピューティング サービス
1. WindowsイメージでMemory limit（-mオプション）を指定してコンテナの生成を試します。

```
docker run --rm -it -m 4G mcr.microsoft.com/windows:20H2 cmd
```

Windowsコンテナへメモリ4Gを割り当ててコンテナが正しく生成されています。

```
Microsoft Windows [Version 10.0.19042.985]
(c) Microsoft Corporation. All rights reserved.

C:\>systeminfo

...(略)...
Total Physical Memory:     4,607 MB
Available Physical Memory: 4,163 MB
Virtual Memory: Max Size:  6,335 MB
Virtual Memory: Available: 5,847 MB
Virtual Memory: In Use:    488 MB
...(略)...
```
Symfony5のチュートリアルに従ってPage作ろうとしたらAn exception occurred in driver: could not find driver

## エラーでた

とりあえずWSL2のUbuntuにチュートリアルに従ってLuckyController.phpを書いて、

```console
$ symfony server:start -d
```

サーバを起動した。
dockerは使っていないので、UbuntuのIPアドレスでないとアクセスできないので、

```console
$ ip a
```

とかして、eth0に記載されてるIPアドレス確認して、
http://xxx.xxx.xxx.xxx.8000
にアクセス。
表題の通り、
"An exception occurred in driver: could not find driver"
などとエラーが出た。

※ ipコマンド叩けない場合は

```console
$ sudo apt-get install net-tools
```

net-toolsとかインストールのこと

## 原因

projectのスケルトンインストールした時点でバンドルされている"Doctrine Migrations"がdevモードでは実際に接続されるのだとかなんだとか。
実際に、.envの初期値を確認すると

```yaml:.env
###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7"
DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=13&charset=utf8"

###< doctrine/doctrine-bundle ###
```

このように、postgresqlに接続するようになっている。

## 対応

Doctrine Migrationsを削除する方法もある見たいだけど、世界に挨拶したいだけで構成を治すのは面倒なので、
一旦、SQLiteで逃げておきたい。

```diff_yaml:.env
###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7"
- DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=13&charset=utf8"
+ DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
###< doctrine/doctrine-bundle ###
```

物理的にファイルを生成しないと解消されないので、symfonyコマンドで以下のようにDBを作成

```console
$ php bin/console doctrine:database:create
```

※ なんかエラー出る場合、php-sqliteがインストールできてないので以下の通りインストールすること

```console
$ sudo apt-get install php-sqlite3
```

これで解消された。

参考：
[Symfonyサーバーの起動時のPostgreSQLエラー](https://www.fixes.pub/program/637478.html)
[[PHP]Symfony 4 とデータベースを使ったCRUDアプリケーションの作り方](https://php-archive.net/php/symfony-4-crud/)
Hiveのcount()で空文字やnullはカウントされるか

```
with t1 as (
  select 'A' as col1
  union all
  select 'B' as col1
  union all
  select ''  as col1
)
select count(distinct col1) from t1 -- 結果は3 (すなわち空文字はカウントされる！distinctを外しても同じ)
```
```
with t1 as (
  select 'A'  as col1
  union all
  select 'B'  as col1
  union all
  select null as col1
)
select count(distinct col1) from t1 -- 結果は2 (すなわちnullはカウントされない！distinctを外しても同じ)
```
【AIエンジニア】月収80万以上を目指す為のPythonのプログラミングスクールの選び方

- Pythonの機械学習エンジニアになって月50万以上稼ぎたい

- そのためにまずはプログラミングスクールの利用を検討している

こういった思いを持つ人に向けてこの記事を投稿しています。


僕は、2018年〜2019年にかけて学生インターンとしてAI開発のベンチャーで働いていました。
現在でも「AI開発は稼げる」というイメージがありますが、確かに**当時その会社では学生の身でありながら月収80万円を超えている人も普通にいました。**

この記事では実際に現場を見てきた経験を踏まえて、
**AIエンジニア志望者がもしプログラミングスクールに通うならどんな基準でスクールを選ぶべきか**
について考えていきたいと思います。

https://qiita.com/ykimura517/items/943a03ded8534f4ed63c
## Pythonのプログラミングスクールを選ぶ前に考えるべきこと

### 実際のAI開発の現場はどうなっているか

まずは**実際のAI開発の現場がどうなっていた（いる）のか**整理しておきたいと思います。
第三次 AI ブームに乗っかる形で、大小様々な企業かディープランニングを使用した事業を展開してきています。

ディープラーニング自体は色々な分野に応用できる技術ですが、**現実の開発案件として多いのが工場等での単純作業の自動化です。**

実際にかつて僕が担当していた業務も、

**ベルトコンベア上の工業製品に混在している不良品をカメラの画像からAIで自動検出する**

といったものでした。

SSDとかその辺のモデルを良く利用していた記憶があります。
参考）https://avinton.com/blog/2018/03/single-shot-multibox-detector-explained1/

社内の別案件でも工場の作業工程の自動化の案件が多かったです。
例えば作業工程から発生する音を解析して何か異常事態が発生していないかを確認するといった案件がありました。

AI開発企業は専門の展示会などに出展し、こういった受託開発案件をとってくるというケースがかなり多いと思います。
自社での専門の開発部署を持たない大企業が、展示会で見かけた開発ベンチャーに割とポンポン仕事を投げている感じでした。
発注者の規模が大きいため、流れてくる金額もそれなりに大きい訳です。

あくまでも僕の周囲のサンプルの話ですが、他社出身の人でも類似の案件を経験してきたというPythonエンジニアによく出会います。

#### 学生で月80万超稼げることもある

**金額的な話で言うと、確かに金払いはよかったのかもしれません。**
僕がいた会社では、学生でも月40万円から80万円程度の報酬をもらっている人がゴロゴロいました。
（ちなみにそういった学生はバイト契約ではなくフリーランス契約でした。）

とはいえ誰でもそれだけの金額を得られるかというと、当然そんなことはないです。
例えば月報酬80万を超えていたのは理科大の院生でしたが、別の会社でも金融関連の案件を抱えていて、とにかく経験豊富でした。
あと、とにかくコーディングが早かったですね（小並感）。


### データ分析の基礎習得が必須

上記のような開発現場の特徴は、**基本的にマニュアルが存在しない**ことです。
特に僕がいた会社では、最近業務の方針転換でディープラーニング分野に進出したばかりでした。
その為**この分野の3年以上経験してきた人間が社内に誰もおらず、学生も含めて各自がネット文献や論文を必死に読み解きながら開発を進めていく状況でした。**

[arXiv](https://arxiv.org/)には何度お世話になったことか……涙


正直、社内全体が混沌としていて、プロジェクト全体の管理やコードの管理もしっかりできていませんでした。

（これはディープラーニング関連のベンチャー企業あるあるなのかもしれません。）

こういった状況に適応していくには、やはり**Python によるデータ分析の基礎習得が必須**だと思います。
**何かに特化した技術を学ぶよりも、汎用性の高い基礎知識を習得することが重要だと思います。**
そもそも社内でも担当する案件が頻繁に変化したり、同じ案件でも「このアプローチは駄目だったから、じゃあ次はこのモデルを使ってみよう」という感じで使用する技術がコロコロと変わっていきました。

機械学習の基本的な考え方が分かっていれば、例えば解析する対象が画像から音声データになろうとある程度は対応可能です。
なのでAIエンジニア志望者は、小手先のテクニックではなくて基礎を習得するように努めるといいと思います。


## おすすめのスクール

この記事はプログラミングスクールを検討している人向けに書き始めたので、最後に僕のお勧めのスクールを挙げておきます。

僕は<a href="https://px.a8.net/svt/ejp?a8mat=3HE6SB+FBWYEY+4HUE+5YJRM" rel="nofollow">アイデミー</a>を推します。
アイデミーは、元々は東大生が始めた小規模サービスでしたが、今では個人の利用者数も50,000人を超えているので、既に知っている人も多いかもしれません。
**特徴は、何と言ってもPythonによるAI開発に特化していることですね。**

僕自身は、アイデミーがまだプログラミングスクールというよりSaaSっぽかった頃に使わせてもらいました。
当時の僕は Python 自体ほぼ未経験だったのですが、

- Pythonの文法
- 線形回帰モデルなどの統計モデルの基本
- 画像処理用のディープラーニングモデルの基本
- Kerasの基本的な使い方

と言ったことを手を動かしながら学べました。

正直僕は自分は物覚えが悪い方だと思うのですが、ここでの基礎があったからこそ後の現場でも手が止まるということはあまりありませんでした。
**どのプログラミングスクールを選ぶか迷っている方は、とりあえずアイデミーを見ておいて損はないと思います。**

<a href="https://px.a8.net/svt/ejp?a8mat=3HE6SB+FBWYEY+4HUE+5YJRM" rel="nofollow">＞＞アイデミーの公式サイト</a>


https://qiita.com/ykimura517/items/cad1ccee690d92508d01

https://qiita.com/ykimura517/items/943a03ded8534f4ed63c
【Google Cloud Day'21】「AI カメラの活用事例に学ぶ「 現場のデジタル化 」と、Google Cloud で利用できるデータの集め方」を視聴して

分析モデルを機器に流し込んでエッジで解析もできる
このアルゴリズムをカメラを操作するコンソール画面からインストールしてカメラ上で分析できるようになる

https://biz.kddi.com/service/iot/iot-cloud-standard/edge-aicamera/
このような機能に近い話な気がする

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/13e4ea88-17cb-26b3-9b9c-e335eb95bf55.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/f4e12309-bb6e-6725-b484-57374f098567.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/f14c40be-b010-f4c1-f60a-a53435b6cb44.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/c703b474-5059-91fd-ac58-5affadd70167.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/8562e17f-2827-37ef-8dc4-bee17d9495b7.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/587f2b04-af54-f92c-ce98-a3f639f5c558.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/82b8df43-2a88-e2a1-5776-c238d6fecd96.png)
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/a273872c-56a7-33bc-989f-98578ece6caa.png)
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/355faf8e-bea8-7065-b4d7-a2f12d39376c.png)
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/cb96bc12-42f3-03ff-1a41-7bd0c53eb4c5.png)
Ruby 配列の要素を削除する(３つのdelete)


#Ruby初学者向け


###配列の要素に対する３つの削除の仕方

例にする配列はこちら↓

```ruby
array = [1, 2, 3, 1, 2, 3]
```
<br>
####１：deleteメソッド

```ruby

array = [1, 2, 3, 1, 2, 3]

array.delete(2)
puts array
# 出力結果＝[1, 3, 1, 3]
``` 

**deleteメソッド**は、
引数にした値(例では2)と**完全一致**した要素のみを削除して配列を返します。

####２：delete_atメソッド

```ruby

array = [1, 2, 3, 1, 2, 3]

array.delete_at(3)
puts array
# 出力結果＝[1, 2, 3, 2, 3]
``` 

**delete_atメソッドは**、
引数に指定した**インデックス番号**の要素を削除して配列を返します。
<br>

`インデックス番号とは`
配列の要素割り振る番号のこと。
最初が１ではなく、**0から**はじまることに注意

参考
[Let'sプログラミング](https://www.javadrive.jp/ruby/array/index2.html)

####３：delete_ifメソッド

```ruby

array = [1, 2, 3, 1, 2, 3]

#奇数の要素を削除した配列を返す
array.delete_if do |n|
  n.odd?
end

# 出力結果＝[2, 2]
```

**delete_ifメソッド**は配列の削除する条件を自由に設定することができます。

例では奇数の値を全て削除しています。
他にも偶数を削除したり、３で割り切れる値を削除したりなど設定可能です。

do~endの部分は**ブロック**といい、ここでは配列Arrayから１つずつ順番に要素を取り出し、do~end内の処理を繰り返し実行しています。

##おわりに

Ruby on Railsの学習もいいけど、Rubyの基礎ってとても大事だな感じる今日この頃。基礎すぎるかもしれないけど少しずつアウトプットしていきます。

誤った記述等ございましたらご教授いただけると幸いです。