OmniAICreator/Qiita-1.07M huggingface dataset:
date_select でつくるセレクトボックスを「年」「月」「日」で区切る


date型のデータについてdate_selectメソッドを使うと簡単にセレクトボックスをつくる


デフォルトでは下記のように年月日の区切りは空白です。

```rb
<div class="birth_date_field">
  <%= f.label :birth_date %>
  <%= f.date_select(
        :birth_date,
        start_year: 1930,
        end_year: (Time.now.year - 18),
        default: Date.new(1989, 1, 1)) %>
</div>
```


もう少し分かりやすくしたいなと思い、区切りにスラッシュを


```rb:年月日の区切りにスラッシュを入れる
<div class="birth_date_field">
  <%= f.label :birth_date %>
  <%= f.date_select(
        :birth_date,
        use_month_numbers: true,
        start_year: 1930,
        end_year: (Time.now.year - 18),
        default: Date.new(1989, 1, 1),
        date_separator: '/') %>
</div>
```


年月日を入れる

```rb:年月日の区切りに「年」「月」「日」を入れる
<div class="birth_date_field">
  <%= f.label :birth_date %>
  <%= raw sprintf(
            f.date_select(
              :birth_date,
              use_month_numbers: true,
              start_year: 1930,
              end_year: (Time.now.year - 18),
              default: Date.new(1989, 1, 1),
              date_separator: '%s'),
            '年 ', '月 ') + '日' %>
</div>
```


|オプション|概要|書き方例|
|--|--|--|
|with_css_class|年月日それぞれでCSSを当てたい場合に利用。実際のCSSはyear,month,dayで指定が可能になる|with_css_classes:'任意のクラス名'|
|order|年月日の順番を変えたい場合に利用。表示させない場合でも必ず年月日全部書く必要あり|order:[:month,:year,:day]|
|use_month_numbers|月の表示を数字にしたい場合に利用|use_month_numbers:true|
|discard_year|年の表示を消したいときに利用|discard_year:true|
|discard_month|月の表示を消したいときに利用|discard_month:true|
|discard_day|日の表示を消したいときに利用|discard_day:true|
|disabled|プルダウンを選択不可にする|disabled:true|
|prompt|指定データがない場合の初期値表示(一番上の表示)に利用|prompt:"--"|prompt:"選択してください"|
|selected|指定データがある場合の指定に利用|selected:Time.now(Date型変数ならOK)|
|start_year|プルダウンの一番上に来る年数を指定|start_year:Time.now.year start_year:2019
|end_year|プルダウンの一番下に来る年数を指定|end_year:Time.now.year-10
end_year:1900|
|date_separator|年月日のフォームを分けた場合の中間に表示する値を指定。|date_separator:'%s'
date_separator:'/'|

@ozackieeささん
>https://qiita.com/ozackiee/items/3c027d07cdeb61df6029
Hatena Blog
>https://blog.inouetakuya.info/entry/2014/01/31/233000
【エラー備忘録】Laravelのログ出力時のエラー　Object of class Laravel\Socialite\Two\User could not be converted to string　

## 状況
Laravelで作ったアプリケーションに、OAithとLaravelのsocialiteを使ってGoogleアカウントでのログイン機能を実装していたときのこと。
Google認証後にコールバックを受け取るところで、画面にエラーが表示されました。

## エラー内容
エラー文はこちら

```:ブラウザ
Object of class Laravel\Socialite\Two\User could not be converted to string　
```
「オブジェクト形式であるUserクラスを、文字列に変換できませんでした」という内容のようです。

## 原因の考察
エラーの原因となっているコードは、この部分でした。

```php:LoginController
public function handleGoogleCallback()
    {
        // Google認証後の処理
        Log::debug('１');
        $googleUser = Socialite::driver('google')->stateless()->user();
        Log::debug($googleUser);　　　　//この行がエラーの原因
        Log::debug('２');
```
handleGoogleCallbackメソッドが実行された際、Log::debug('1');はログ出力出来ていますが、$googleUserと'2'はログ出力できていませんでした。

Log::debugは文字列をログ出力するものですが、$googleUserの中身はオブジェクト形式。よって、先述の内容のエラーが出ていたようです。

## 解決法
ログ出力する際、print_r()を使って$googleUserを文字列に変換します。
※print_r()は、第二引数にtrueをとると、結果を文字列として関数の戻り値にすることができる。



```php:LoginController
public function handleGoogleCallback()
    {
        // Google認証後の処理
        Log::debug('2');
        $googleUser = Socialite::driver('google')->stateless()->user();
        Log::debug(print_r($googleUser, true));   //書き換える
        Log::debug('3');
```

これでエラーはなくなり、また$googleUserの中身をログ出力することもできました。
【Laravel】リレーションのカラムを指定して配列を作る

```php:リレーションを取得
$test->questions
```

リレーションでbelongsToのモデルを取得して、尚且つそのカラムを指定して配列を作りたい場合があります。
どうすればよいのか？

array_column()を利用します

````php
array_column(配列, 'カラム名')
````

これを利用すると、カラムの値で配列をつくることができます

なので、下記のように書きます

```php:リレーションのカラムを配列にする
array_column($test->questions, 'id');
```

これでリレーションのidの配列が作成されました。

```php:実用例
in_array('1', array_column($test->questions, 'id'));
```
in_arrayの使って書けば、リレーション先のidで'1'があるか確認できる
このように配列にまとめてチェックしたい場合、主にarray系のメソッドを利用したい場合に利用できるので、
知っておくとすぐに問題解決できるしょう
【OS】/centos7/ flatpak

## 概要
Linux デスクトップ向けのソフトウェアデプロイメントおよびパッケージ管理を行うユーティリティソフトウェア
⇒GUI を備えたアプリケーションに限定している
⇒Flatpak でインストールされたアプリケーションは、実行時にホスト環境から隔離（サンドボックス化）される。

デスクトップエントリの登録はしなくても表示された。

## versionを確認する

```
flatpak --version
>>Flatpak 1.0.2
```

## versionをアップデートする

```
yum update flatpak
flatpak --version
>>Flatpak 1.0.9
```
## リポジトリの追加

```:公式のリポジトリを追加する。
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
```

## インストール
### (ブラウザ)firefox
参照↓
https://flathub.org/apps/details/org.mozilla.firefox

```:インストール
flatpak install flathub org.mozilla.firefox
```
```:実行
flatpak run org.mozilla.firefox
```
### (ペイントソフト)Pinta
```:インストール
flatpak install flathub com.github.PintaProject.Pinta
```
```:実行
flatpak run com.github.PintaProject.Pinta
```
## アプリの情報を確認する

```
flatpak info <アプリ名>
```
例

```
flatpak info com.github.PintaProject.Pinta
```
→locationなどがわかる。
GASでトライオートFXの利益確定を毎日自動集計してスプレッドシートにまとめる

# はじめに
こんにちは。新しいPC買って届いたのですが、セットアップが面倒でまだ開けていません、筆者です:bow:

さて、トライオートFXでコアレンジャーで外貨を自動売買しているのですが、日別・月別でどれくらい利確しているのかを可視化するべく、GASでスプレッドシートに実績レポートするスクリプトを書いたので(1年くらい前に)、共有しようと思います:v:

# 前提
1. トライオートFXで利確の度にGmailにメールが届きます.
1. 1のメールには、`【トライオートfx】注文成立のお知らせ`というラベルを付加しています.

# 処理
1. 指定のラベルがついたメールをすべて取得.
2. 1の中から利確したメールのみ処理開始.
3. 2のメールに対して利確値を正規表現で取得.
4. 3の値を配列に追加.
5. 1に対して4まですべて完了後、スプレッドシートに書き記す.
6. 1-5までの処理を日別実行のトリガーとして設定.

# 実スクリプトはこちら
```js
const getColumnFromIndex = i => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split``[i - 1];

const getData = () => {
  var data = {}, offset = 0, limit = 500;
  while (true) {
    // 処理1
    var threads = GmailApp.search('label:【トライオートfx】注文成立のお知らせ', offset, limit);
    offset += limit;

    for (thread in threads) {
      for (key in threads[thread].getMessages()) {
        var body = threads[thread].getMessages()[key].getBody();
        if (body.match(/損益/m)) { 処理1
          
          // 処理2
          var ymdhis = body.match(/\d{4}\/\d{2}\/\d{2}\s\d{2}:\d{2}:\d{2}/)[0];
          var transaction_ym = Utilities.formatDate(new Date(ymdhis), 'Asia/Tokyo', 'yyyyMM');
          var transaction_d = Utilities.formatDate(new Date(ymdhis), 'Asia/Tokyo', 'dd');
          
          // 処理3
          var price = body.match(/(\d+)円/)[1];
          if (! data[transaction_ym]) {
             data[transaction_ym] = {};
          }

          // 処理4
          data[transaction_ym][transaction_d] = (data[transaction_ym][transaction_d] ? parseInt(data[transaction_ym][transaction_d]) + parseInt(price) : price);
        }
      } 
    }
    if (threads.length < limit) break;
  }
  return data;
}

const makeReport = () => {
  const data = getData();

  // 処理5
  var sheet_data = [];
  sheet_data.push([]);
  sheet_data[0].push('');
  for (ymd in data) {
    sheet_data[0].push(ymd);
    for (var i = 1; i <= 31; i++) {
      if (! sheet_data[i]) {
        sheet_data[i] = [];
        sheet_data[i].push(i);
      }
      
      if (data[ymd][('0' + i).slice(-2)]) {
        sheet_data[i].push(data[ymd][('0' + i).slice(-2)])
      } else {
        sheet_data[i].push(0)
      }
    }
  }

  var path = 'A1:' + getColumnFromIndex(sheet_data[0].length) + sheet_data.length;
  SpreadsheetApp.getActiveSheet().getRange(path).setValues(sheet_data);
}
```

# 実行結果
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86984/20718eb9-3d26-bba8-fa83-b9ee23c2014b.png)

# おわりに
トライオートFX使用している方はおすすめです！
トリガーセットしないと毎日自動で動いてくれないのでご注意を:pray:

それでは！
Windows で VSCode + WSL2 で cfn-python-lint を動かしてみる

## 概要

Windows + WSL2 (Windows Subsystem for Linux 2) の VSCode (Visual Studio Code) に cfn-python-lint を導入してみたのでその備忘録として残しておきます。
私の場合 WSL2 がすでに導入済みだったので WSL2 の導入方法については省略します。 

## 環境

- Windows 10 (1909)
- WSL2 Ubuntu 20.04.1 LTS
- VSCode 1.51.1 

## 手順
### WSL2 のインストール

WSL や 仮想マシンプラットフォーム を有効にしたり、Ubuntu インストールしたりする必要がありますが手順は省略.....
`WSL2 インストール` でググるといろいろと手順が出てくるかと思います。

### WSL2 に cfn-lint で必要なミドルウェアをインストール

- python3
- pip3
- cfn-lint

※ 上記すでに導入済みの場合はスキップ

- python3 インストール
    `$ sudo apt install python3`

- pip3インストール
    `$ sudo apt install python3-pip`

- cfn-lint インストール
    `$ pip3 install cfn-lint`

- cfn-lint の配置場所を確認
    `$ which cfn-lint`
    
    たぶん ↓ に配置されてる
    `/home/ユーザ名/.local/bin/cfn-lint`
  

### VSCode でプラグインをインストール

- `Remote - WSL`
- `CloudFormation Linter`

#### Remote - WSL のセットアップ

1. `Ctrl` + `Shift` + `P`
1. `Remote-WSL: New Window` を入力して選択
1. VSCode を再起動
1. VSCode の左下が `WSL-Ubuntu20.04` となっていればOK

#### CloudFormation Linter のセットアップ

1. `Ctrl` + `,` で 設定画面 を開く  
1. `Cfn Lint: Path` に which で確認したパス入力  
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594215/967a2485-ae49-768e-23de-2f5202d473d6.png)  
    `cfn-lint` -> `/home/ユーザ名/.local/bin/cfn-lint`  

### おまけ

- Windows のエクスプローラーで `\wsl$` と入力するとエクスプローラー上で WSL のファイルが見れるのでショートカットやネットワークドライブとかに登録しておくと便利。
- 逆に Ubuntu 内で `/mnt/c` に接続すると Windows の Cドライブ にアクセスできる。
UITextViewの選択を無効化しリンクのみタップを可能にする

# はじめに
どうも@kaneko77です
たまーにあるリンク化したテキストを実装する際、
リンク以外もタップできちゃう問題発生する時あると思います。
今回はそちらに焦点を当てて解決策を共有していきたいと思います。

## 環境
Xcode13
Swift5.5
IOS15

## 遭遇シーン
以下挙動があると思います。
リンク入れたけど他タップできるやん！！ですね。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/b43359d1-eadb-641f-517a-ed59245c3fb2.gif" width="300px">
それをリンクのタップだけ機能して他はタップできないように実装しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397376/3df49664-e58f-c5a1-e714-b47431689d53.gif" width="300px">
## コード
それではどういう風に書いてどういう風に呼び出すか書いてきます。
大層に呼び出しとか言ってますが、実際にはUITextViewのカスタムクラスを作成して、
そのカスタムクラスを呼び出す形になっています。

```swift:　呼び出し側
let hogeText: CustomTextView = {
    let textView = CustomTextView()
    textView.translatesAutoresizingMaskIntoConstraints = false
    textView.font = .boldSystemFont(ofSize: 20)
    textView.textColor = .black
    textView.textAlignment = .center
    textView.isSelectable = true
    textView.isEditable = false
    textView.isScrollEnabled = false
    let text = "設定アプリを開きたい場合は⑴こちら\n Googleを表示したい方は⑵こちら"
    let attributeds = NSMutableAttributedString(string: text)
    attributeds.addAttribute(
        .link,
        value: UIApplication.openSettingsURLString,
        range: NSString(string: text).range(of: "⑴こちら")
    )
    
    attributeds.addAttribute(
        .link,
        value: "https://www.google.co.jp/",
        range: NSString(string: text).range(of: "⑵こちら")
    )
    textView.attributedText = attributeds
    return textView
}()
```

```swift:　呼び出し元
import UIKit

class CustomTextView: UITextView {

    // MARK: - リンクのみタップ可能にする
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        guard let p = closestPosition(to: point),
              let range = tokenizer.rangeEnclosingPosition(
                p, with: .character,
                inDirection: UITextDirection(rawValue: UITextLayoutDirection.left.rawValue)
              ) else {
                  return false
              }
        let link = attributedText.attribute(
            .link, at: offset(from: beginningOfDocument, to: range.start), effectiveRange: nil
        )
        return link != nil
    }

    // MARK: - テキスト選択時にメニューの表示を禁止する
    override func becomeFirstResponder() -> Bool {
        return false
    }

}

```


# 終わりに
今回はリンクのみタップ可能になる方法のご紹介でした。
かなり簡単にイライラする要因がなくなるため嬉しいですね。

## 参考にしたサイト
https://qiita.com/taka4/items/45736821bd20b10193a1
画像付いてたり付いてなかったりするUITableViewCellは UIStackViewでサクッと作れる

画像掲示板で、レスに画像がついてるときもあれば無いときもある、というようなパターンでのセルです

従来はImageCell, TextCellみたいに分けちゃったほうが早かったですが、StackView使えるならCellの定義は一個ですみますね

先に構成見せたほうが早いと思うので、こうです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48695/7169a189-9928-8938-38b3-a332b1ab87b8.png)

DetailCellの中にstackViewを置きます

```
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
```

内で、サムネ.isHiddenを出し分けるだけですね

注意点として画像なしセルの表示のあとに画像付きセルが表示されると、AutoLayoutのエラー解消ログがデバッグログに出ますね

これはおそらくTableViewの高さ計算とサムネのありなしの高さ計算が競合しちゃってますね
なのでサムネの高さ計算の優先度をちょっと下げると解消します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48695/c9feb7cb-9994-6bd6-2769-a157e958b649.png)


自分の備忘録的な記事なのであっさりですみません

質問あればコメントください
Format String Attack〜printfの脆弱性への攻撃〜

# Format String Attackとは

`printf()`,`syslog()`,`err()`などの関数の脆弱性を突いた攻撃方法。
書式文字列攻撃。

# printfの脆弱性

## printfの書式

まずは基本に立ち返ってみよう。

```C
printf("I am %s", name);
```

ここで`I am`が通常の文字、`s`が変換指定子、`name`が変換指定子に対応する実引数である。変換指定は`%`と変換指定子からなり、後に続く実引数を取り出す。

##printfの脆弱性の成立条件

変換指定子を使わずに下記のようにすると、攻撃者がprintf()の出力内容をコントロールすることができる。

```C
printf(str)
```

##printfの脆弱性の原因

変換指定子に対応する引数の数をチェックする仕組みが存在ないので、引数が与えられているものとしてスタックを参照する。



# 実際にしてみる

```C
#include<stdio.h>

int main(void) {
    char str[128];
    fgets(str, 128, stdin);
    printf(str);
    return 0;
}
```

**fgets**で標準入力から文字列を受け取り、**printf**で出力するプログラムだが、`printf("%s", str)`ではなく、`printf(str)`となっている。

```zsh
% gcc fsa.c
% ./a.out       
123
123
% echo -e "abc %x"|./a.out 
abc 120a8
% echo -e "aaaa %x %x %x %x %x %x %x %x %x"|./a.out
aaaa 120a8 0 8bc7e6c 130a8 0 ee6c2610 ee6c2600 61616161 25207825
% echo -e "bbbb %x %x %x %x %x %x %x %x %x"|./a.out
bbbb 120a8 0 d842e6c 130a8 0 ebd2d610 ebd2d600 62626262 25207825
% echo -e "cccc %x %x %x %x %x %x %x %x %x"|./a.out
cccc 120a8 0 1e9a9e6c 130a8 0 e041d620 e041d610 63636363 25207825
% echo -e "abcd %x %x %x %x %x %x %x %x %x"|./a.out
abcd 120a8 0 10dc8e6c 130a8 0 dfe4b610 dfe4b600 64636261 25207825
```

`echo -e "abc %x"|./a.out`と入力すると、`print("abc %x")`が実行される。
ここで`%x`は16進数を表示させる変換指定子なので、スタックの一番上に格納されているものが表示される。
`aaaa`のとき出力の9個目の**61616161**というところに格納されていることが分かる。
`bbbb`のときは**62626262**,`cccc`のときは**63636363**,`abcd`のときは**64636261**(リトルエディアンの場合)となる。

#応用編

https://tomomon.jp/2021/06/13/ksnctf4/
Rust で Optional の None チェック

## どう書くの

```rs
if Optional型.is_none() {
    return;
}
```

## おまけ

どう書くかわからなくてこんな感じに書いてたら、

```rs
if let Some(_) = manager.get(msg.guild(&ctx.cache).await.unwrap().id) {

} else {
    return;
}
```

コンパイラが教えてくれた

```bash
warning: redundant pattern matching, consider using `is_some()`
  --> src/handler/mod.rs:25:16
   |
25 |         if let Some(_) = manager.get(msg.guild(&ctx.cache).await.unwrap().id) {
   |         -------^^^^^^^------------------------------------------------------- help: try this: `if manager.get(msg.guild(&ctx.cache).await.unwrap().id).is_some()`
   |
   = note: `#[warn(clippy::redundant_pattern_matching)]` on by default
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching

warning: 1 warning emitted
```

```rs
warning: this boolean expression can be simplified
  --> src/handler/mod.rs:25:12
   |
25 |         if !manager.get(msg.guild(&ctx.cache).await.unwrap().id).is_some() {
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `manager.get(msg.guild(&ctx.cache).await.unwrap().id).is_none()`
   |
   = note: `#[warn(clippy::nonminimal_bool)]` on by default
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
```
Laravel env関数の環境変数が取得できない

プログラミング初心者です
##解決したい問題
.envファイルで定義した環境変数をPHPファイルで呼び出したい。

```
APP_NAME=Laravel
```
##解決方法①
env関数を使います。

```
env('APP_NAME')
```
##問題発生
でもこのまま実行しても存在しないというエラーが出ちゃいました。
tinker使って調べると・・・

```
$ php artisan tinker
Psy Shell v0.9.12 (PHP 7.3.24-(to be removed in future macOS) — cli) by Justin Hileman
>>> env('APP_NAME')
=> null
>>> 
```
中身何も入っていなくnullが返されてしまいます。
##解決方法②

調べてみると、キャッシュを消せば手っ取り早いということで、このコマンドを実行


```
php artisan config:clear
```
自分は変更が反映されるようになりました！
##備考

そしてもう一つこのコマンドを使ってのやり方もあるんですが、configファイルを使わなきゃいけなかったりと注意しなくてはならない点があるため、理解したら追記しようかなと思います。

```
php artisan config:cache
```
##追記7/4
```php artisan config:cache```を実行してしまって、　存在しないエラーが出てかなり焦りました。
そして
```php artisan config:clear```をしてみた反映されました
②マイグレーションファイルのすすめ　外部キー

##初めに
今回は外部キーとリファレンスについてまとめます。
こちらは②マイグレーションファイルのすすめ②ですので、よければ①もご覧ください。
[マイグレーションファイルのすすめ](https://qiita.com/masarumosu/items/c79e5b4413388d1fc5a1)

以下の記事を参考にさせていただきました!
[外部キーの概要と制約を使うことのメリット・デメリット](https://qiita.com/kamillle/items/5ca2db470f199c1bc3ef)

##　外部キー　概要

```
create_table(:users) do |t|
  t.string :name, null: false
end

create_table(:user_tweet) do |t|
  t.references :user, null: false, foreign_key: true
end
```

##外部キーとは
テーブル同士を紐付ける際に用意されるカラムのこと。
例えば以下の二つのテーブルは、1ユーザーが複数のツイートを持っており、ツイートテーブルのuser_idが```user.id```の値を格納することで二つのテーブルを紐付けている。
この時ユーザーテーブルのidカラムは主キー、ツイートテーブルのuser_idが外部キーである。

ユーザーテーブル

|id|user|         
| --- | --- |   
|1|KEN|            
|2|MIKE|        

ツイートテーブル

|id|user_id|content|
| --- | --- | --- |
|1|1| Hello|
|2|1| How are you? |
|3|2| こんにちは　|

##外部キー制約とは
主キーと外部キーを使った制約で利用した場合、以下の制限がある。
1. 存在しない値を外部キーとして登録することはできない
2. 子テーブルの外部キーに値が登録されている親テーブルのレコードは削除できない

###1. 存在しない値を外部キーとして登録することはできない
ツイートテーブルにデータを登録する際に、user_idがuserテーブルのidカラムに存在しない値(例えば nullや3など)を指定するとエラーが生じる。

###2. 子テーブルの外部キーに値が登録されている親テーブルのレコードは削除できない
ユーザーKENを削除する際に、user_idの値が1のツイートが存在する場合は、ユーザーKENを削除することができない。
※ KENを削除する場合は、Userモデルでdependent: :destroy を使用する必要がある。

##外部キーのメリットとデメリット
存在しない値が、登録されることを防ぐことがきる為、データの整合性が保たれる。
親テーブルの存在しない子テーブルが発生することを防げる。

##外部キーの作成方法
外部キーの作成には以下の2パターンがある。

```
create_table(:users) do |t|
  t.string :name, null: false
end

create_table(:tweet) do |t|
  t.references :user, null: false, foreign_key: true
end

OR

create_table(:users) do |t|
  t.string :name, null: false
end

create_table(:tweet) do |t|
  t.references :user
end

# add_foreign_keyは後から外部キー制約を貼りたい場合にも使える
add_foreign_key(:tweet, :users)
```

```t.reference :user```によりuser_idカラムを作成している。
*```foreign_key: true```がなければ外部キー制約がつかないので注意！

##まとめ
外部キーは、テーブル設計に欠かせない知識なのでぜひ覚えましょう！
人のことは言えないので僕も覚えます！笑
Node.js とは何なのか？なぜ学ぶ必要があるのか？

<h1>
Node.jsってなんやねん？なんで知っとかんとあかんねん？
</h1>
<p>
という超初歩的な疑問に対して答えようと思うのじゃ。<br>
元々はphpとSQLというウェブの作り方はもう時代遅れだから、既存のサイトを全てnodeとnon-SQLに置き換えたいというプロジェクトへのオファーがあり、２０年以上ウェブの現場から遠ざかっていた身としては、nodeっていうのはphpみたいなサーバー側の言語かのぉくらいに思っていたわけですが、調べると、サーバー側で動くJavascriptっていう言い方がよくされていて、さらに触れてみると、その言い方も間違いで、<strong>サーバー側でJavascriptを動かす為の実行環境と便利なモジュール群</strong>が正しい表現の仕方かなと。<br>
元々javascriptって、ブラウザ上でしか動かないんで、サーバーサイドはphpとかpythonとか他の言語で書かないといけなかったわけです。<br>
で、そんなんやったら、両方で動いたほうが便利やん！って思ったギークたちがGoogleからV8エンジンを運び出し、両方で動くようにしてしまったわけです。<br>
つまり、javascriptでOSの機能とかファイルシステムにもアクセスできてしまうわけです。phpで書いていたのを、javascriptの.jsで代替できるっていうことでもあります。<br>
で、どうやって使うねん？と思うかも知れませんが、<a href="https://nodejs.org/en/">https://nodejs.org</a>からNode.jsをあなたのコンピューター（サーバー）にダウンロードするだけです。<br>
で、それから、どうやって使うねん？って？　基本的にコマンドラインからの操作か、コードエディタでサーバー側コードをJavascriptで書いて、サーバー側で実行です。クライアントサイドのjavascriptはブラウザで動作確認できるよね？<br>
nodeをインストールしたら、コマンドラインを立ち上げて、node とコマンドを打つだけで環境が立ち上がります。
<pre>
<code>
ubuntu@ubuntu-aurora-r4:~$ node
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> 
</code>
</pre>
で、普通にjavascriptのコードを打つとちゃんとコードが実行されているのが分かります。<br>
<pre>
<code>
ubuntu@ubuntu-aurora-r4:~$ node
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> 
> let  x=11; let y=15; let sum=x+y; console.log(sum)
26
> const name='henoheno'; console.log(name);
henoheno
> 
</code>
</pre>

ブラウザが無くても、OSの中（つまりサーバー内）でjavascriptが動いてるよね？<br>
つまりこれがnodeの力。<br>
ブラウザからフォームとかを通してjavascriptで書かれたリクエストが来ると、サーバー側のjavascript(node)でそのリクエストを処理して、送り返すっていう感じ。
</p>
<h2>普通のjavascriptと何が違うんじゃい？</h2>
<p>
例えば、ブラウザ側で使われるjavascriptにあるような、Windowオブジェクトとか、Documentオブジェクトはありません。だってOS側の操作にブラウザとか画面は関係ないんだから。<br>
その代わりに、fsコマンドや、Processオブジェクトなど、ファイルの操作に使うようなオブジェクトやメソッドが存在します。<br>
ブラウザ側ではAPIからデータを持ってくる場合、fetch()を使いますが、node側ではrequestモジュールを使ったり、そういった細かい違いはあるけども、結局javascriptです。javascriptのシンタックスとか書き方で動きます。<br>
基本的に、元々のnodeに入ってるモジュールはグローバルと言って、ほんの少ししか入っていないので、ほぼ裸の状態です。色々便利なモジュールは、別途インストールして自分で服を着ていかないといけません。<br>
モジュールのインストールや、操作はnpmっていうモジュールをインストールして行います。
こいつがいないと、node環境での作業は捗りません。まさにnode界のドラえもんです。<br>
ノビグラマー「npmえもん！簡単にAPIをたたいてデータを持ってきてくれる道具なんか無いかな！くそだるくて、一から書いてられないよ！」、npmえもん「ノビくんはしょーがないなー、いつも楽することばっかり考えて。”Request～”☆☆☆彡！！！。使い方は公式ドキュメントで勝手にしらべるんだよ。」っていう感じ。
</p>
<h2>なんでnodeやねん！phpでもええんやないのか？</h2>
<p>
nodeはNetflix、Facebook、PaypalやAmazonでも使われています。<br>
勉強していくとわかるんだけど、どちらかというと今までみたいなメニューがずらっと並んでてリンクがあるようなサイトよりも、Web APPやAPI、ヘッドレス、シングルページのウェブに非常に向いてる感じ。<br>
デプロイの仕方も全然違います。<br>
nodeの特徴としてよく言われるのが、”ノンブロッキングI/O”というコンセプト。<br>
javascriptはシングルスレッドで、１個づつしかコードを実行できないんだけど、ポイントは”待ち時間”。<br>
料理に例えると分かりやすい。シングルスレッドなので、シェフは一人でサラダとスープとステーキとデザートを作るとする。<br>
スープから作るとすると、スープを煮込んでる間にサラダの準備とステーキの仕込みが出来るのが、”ノンブロッキング”。スープが仕上がるまで、鍋の前で待っていないといけないのが、”ブロッキング”。phpは元々これ。<br>
この場合、ステーキが焼き上がるまで、デザートの準備も出来ないことになり、全てのコースが揃うまで膨大な時間が必要になる。<br>
その点、ノンブロッキングは一度コードを実行させると、待ってる間に他のコードも複数実行させる事が出来る。<br>
ここでJavascriptのPromiseが、出来上がったでーって知らせてくれて、次の処理の段取りも立ててくれる。<br>
nodeはこの点が非常に優れており、結果的に多くのリクエストをすばやく効果的に捌けるため、超軽くて速いっていう事になる。<br>
実際にサーバーの立て方、ディレクトリの構成、ページの作り方を少しづつアップしていく予定です。がんばれ、俺。
</p>
[次回！nodeでサーバーを立てる](https://qiita.com/monsoonTropicalBird/items/fe51c431d1abbc68ff7c)
PhpStorm (JetBrains) で開いているファイルをGitHubでも開きたい

Slackで「このファイルを見てほしいですけど」という時にGitHubのURLで共有しています。

すごく便利なのですが、ファイルをいちいちGitHubから選択する必要があり、深いフォルダにあるファイルの場合には一苦労です。
OctTreeや[Gitako](https://chrome.google.com/webstore/detail/gitako-github-file-tree/giljefjcheohhamkjphiebfjnlphnokk)の検索機能もとても優秀なのですが、もっと手早く共有できないかと思っていました。

VSCodeであればファイルを右クリックして「Open in GitHub」からGitHubで開いたり、URLをコピーしたりといった機能があります。

![Screen Shot 2021-06-13 at 2.31.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/71aae408-027c-18bc-a9d0-942b0aed4b9d.png)

PhpStormにもそういう機能が無いかな…と思っていたいたところ、ありました。

1. Preferencesを開き、Menus and Toolbarsを選ぶ
1. 「Editor Tab Popup Menu」（ファイルタブ） もしくは 「Project View Popup Menu」（左ファイル一覧）を選ぶ
1. メニューを追加したい箇所を選択し、上部のプラスマーク（＋）をクリックする
1. Open on GitHub を選択して保存する


![Screen Shot 2021-06-13 at 2.28.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/6d0fd4e7-1b07-6b0a-5121-1cc6e591c34c.png)


![Screen Shot 2021-06-13 at 2.28.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/c1947e65-dddf-1a2f-0355-2e28e6cb4024.png)

これで快適になります！
newとbuildの違い


### newとbuildってどう使い分けるの？
buildは、buildはアソシエーションを関連づけさせているときに使用し
外部参照キーを自動でセットしてくれる
親要素への結びつけが必要な場合はそこを自動でやってくれる
モデルを関連付けしたときにbuildを使う
buildはnewのエイリアス（ショートカットキー）
buildは新しい書き方で
buildは親要素から子要素のデータをセットしてくれる便利なことをするやつ
newは子要素を自分で記述する必要がある

＜例＞
※@post = @user.posts.buildは、@post = Post.new(user_id: @user.id)と同じ。
※user.rbに「has_many :posts」があると、「Userインスタンス.posts.build」というメソッドが使える」ようになる。
これは「Userインスタンスに紐付いたPostインスタンスを生成する」メソッド。
アソシエーション部分で働いている色々なモデル内まとめ

### belong_to 
この関連付けをされているクラスには外部キーがあること前提
外部キーが別クラスにある場合はhas_oneを使用する必要がある

---

### :optional
belong_toで使えるオプションの一つ

> 公式
> :optionalオプションをtrueに設定すると、
> 関連付けされたオブジェクトの存在性のバリデーションが実行されないようになる。
> 

☆値が空で来たときはエラーを返さずに、その空情報をなかったかのように振る舞わせることができる
☆optional: trueはpresence:trueと逆のことをしている
☆外部キーのnilを許容してくれる
☆アソシエーション組んである状態のため親要素がないとエラー！って出てしまうモデルのチェックを回避してくれる

今回は親の情報が入った時点で子要素側に親_idの情報が渡すことができるようになる
そのため親が存在していないと子は保存できない状態にあるということ
いつ親の要素が入るのか
親と子の要素が一緒に登録されるからことここの記述が必要になるという特殊な状態
一旦子要素が親要素がない状態でも作られるようにしていて
親要素ができたタイミングで子要素を紐付けをさせるようにしている

---

### reject_if: :all_blank
accepts_nested_attributes_forをすると空の文字列が入っているデータを弾いてくれる

---

### allow_destroy: true

モデル経由から別モデルを削除する時に必要なオプション
親要素側から削除する必要がある
※今回はネストさせて使用するデータベース ＝ controllerがない ＝ destroyアクションがないという状態
コントローラがない特殊なモデルaccepts_nested_attributes_forの関係の時どう削除するか
自分に紐づいているコントローラを持たないモデルのデータを消したいときに使う

---

### dependent: :destroy
親要素がいなくなってしまったときに子要素が浮いた状態にならないように削除される

---

### belongs_toとhas_oneのどちらを選ぶか

2つのモデルの間に1対1の関係を作りたいのであれば、いずれか一方のモデルにbelongs_toを追加し、もう一方のモデルにhas_oneを追加する必要があります。
外部キー(foreign key)をどちらに置くかできまる

-----
【VBS】ネットワークドライブの割り当てをワンクリックで処理する

#はじめに
WindowsPCからFTP等のファイル管理サーバに自端末を繋げる際、エクスプローラで「ネットワークドライブの割り当て」という作業を行います。
現場によってはファイルサーバとの繋ぎっぱなしは禁止されていたりするためこの割り当て作業を毎日行う必要があります。
ですが、毎日毎日この割り当て作業を行うのはちょっと面倒なのでVBScriptで一連の処理を自動化してみました。

#スクリプト
3行で収まる簡単な処理になりました。
修正する部分は3行目のネットワークドライブのフルパスとログイン時に求められるユーザー名とパスワードになります。接続時の認証が必要ないのであれば<, "user", "passwd">の部分は消してしまって問題ないです。

```vbs:Windows_to_NetworkDrive.vbs
Dim objWshNetwork
Set objWshNetwork = WScript.CreateObject("WScript.Network")
objWshNetwork.MapNetworkDrive "Z:", "ネットワークドライブフルパス", False, "user", "passwd"

```
#まとめ
上記スクリプトは誰でも簡単に試せるもものになっていますので、お気軽にお試し下さい。
後はタスクスケジューラ等にジョブとして登録し、端末起動時に自動実行すると設定すれば毎日の業務開始準備が非常にスムーズになると思います。
本記事は以上になります。ありがとうございました。
gitでpushする際に毎回パスワードを聞かれる

#はじめに
pushする時に毎回パスワードとユーザー名聞かれるのめんどくさかったので調べた。
#対策
こちらのサイト[[1]]を参考にした。
どうやらhttps通信だとだめでssh接続にしないといけないよう。
冷静に考えれば確かにそう。
既存のリポジトリのURLを変更。

```
git remote set-url origin git@github.com:ユーザ名/レポジトリ名.git
```
httpsからssh接続に変更。
そしたらsshの鍵のパスワードを聞かれるようになってしまった。
これもめんどくさいので調べてこちらのサイト[[2]]を参考にした。
参考サイト通りにしたら成功、パスワードが聞かれなくなった。

#おわりに
調べたら出てくる時代に感謝。
もうちょっと成長したら参考にするばっかじゃなくて自分で１から記事を書いて貢献します。
それではまた。
#参考文献
[1]:https://qiita.com/rorensu2236/items/df7d4c2cf621eeddd468
[[1]]:git パスワード を毎回聞かれる問題の解決方法
[2]:https://bbh.bz/2019/09/02/soltion-that-git-asks-for-pass-everytime/
[[2]]:gitにpushする時、毎回SSHキーのパスワードを聞かれる問題の解決方法
【SwiftUI】Chartsを使って線グラフを表示する

## はじめに
今回はSWiftUIを使って線グラフを表示していきたいと思います。（厳密にはSWiftUIでUIViewを使います）
使用するライブラリは[Charts](https://github.com/danielgindi/Charts)です。

## 1. 作った物
本記事のコードを用いることでこのようなグラフを表示することができます。

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233342/9100d506-c1c7-a518-4019-9fdfc7ddd5f0.png)


## 2.ライブラリをインポート
CocoaPodからライブラリを導入します。
まずはプロジェクトディレクトリで`pod init`

続いてPodfileに`pod 'Charts'`を追記して`pod install`

あとはプロジェクト内で`import Charts`とすれば使えるようになります。


## 3.SwiftUIでUIViewを使う
Chartsライブラリですが、SwiftUIには対応しておらず、従来のUIKitのライブラリとなります。

そのため使うためにはSwiftUIでラップする必要があります。

SwiftUIしか触ったことがない私はこの時点で？？？でしたが、
調べてみて何となくわかってきました。

### UIViewRepresentableプロトコル
UIKitのクラスをラップするには`UIViewRepresentable`プロトコルを使用します。

ラッパークラス（構造体？）のLineChartを作成します。(ここの名前は自由です）
そして`LineChartView`というのが今回ラップ対象のクラスです。


```swift
struct LineChart : UIViewRepresentable {
    func makeUIView(context: Context) -> LineChartView {
       // ここでViewが作られるイメージ
    }
        
    func updateUIView(_ uiView: LineChartView, context: Context) {
       // 値が更新された時に呼び出される処理
    }

}

```

また、UIViewRepresentableプロトコルは`makeUIView`関数と`updateUIView`関数の実装が必須になります。

`makeUIView`で表示するViewが作られるイメージ
`updateUIView`では値が更新された時に呼び出される処理を書きます。例えば数値を追加した時にそれを動的にグラフに反映する時に使用します。今回はそこまで実装しません。


### 実装

こちらが全文となります。makeUIViewの箇所がメインとなります。
dataSetをdataにいれてdataをチャートに反映する。
というだけですのでそこまで複雑な内容ではありません。



```swift
import SwiftUI
import Charts

struct LineChart : UIViewRepresentable {
    func updateUIView(_ uiView: LineChartView, context: Context) {
        // update
    }
    
    func makeUIView(context: Context) -> LineChartView {
        // グラフに表示する要素
        let lineChartEntry : [ChartDataEntry] = [
            ChartDataEntry(x: 0, y: 0),
            ChartDataEntry(x: 1, y: 1),
            ChartDataEntry(x: 2, y: 2),
            ChartDataEntry(x: 3, y: 3),
            ChartDataEntry(x: 4, y: 4),
            ChartDataEntry(x: 5, y: 5),
        ]
        
        let chart = LineChartView()
        let data = LineChartData()
        let dataSet = LineChartDataSet(entries: lineChartEntry)
        
        // データセットを作ってチャートに反映
        data.addDataSet(dataSet)
        chart.data = data
        
        return chart
    }
}

struct ContentView: View {
    var body: some View {
        LineChart()
    }
}
```

## おわりに
無事SwiftUIでChartsを使うことができました！
次回は値を動的にグラフに反映する方法やグラフの見た目をカスタマイズする方法を投稿したいと思います。
よく使うGoogle Apps Script Editorのショートカットキー for Mac

|ショートカット|アクション|
|----|----|
|⌘+r|スクリプトの実行|
|⌥+←|前の単語へ移動|
|⌥+→|次の単語へ移動|
|⌘+←|行頭へ移動|
|⌘+→|行末へ移動|
|⌥+↑|行を上に移動|
|⌥+↓|行を下に移動|
|⇧⌥+↑|行を上にコピー|
|⇧⌥+↓|行を下にコピー|
|⇧⌥+f|コードを一括整形|
【Java】身長/体重を入力したらBMIが分かるプログラム

#作りたいもの
1.身長と体重を入力する
2.BMIの計算結果を表示する
3.「低体重、普通体重、肥満」のどれかの評価を付ける

以下のソースコードは、Java独学2か月くらいの僕が書いたものです。
@shiracamus さんからアドバイスいただけたので、初学者の方は、ぜひ見比べてみてください。
（お～！ってなりますｗｗ）


#ソースコード（※参考にしないほうがいいやつｗ）

```Test1.java
import java.util.Scanner;

public class Test1{
	public static void main(String[] args) {
		try {
			@SuppressWarnings("resource")
			Scanner scan = new Scanner(System.in);

			System.out.print("身長(m)：");
			double inputHeight = scan.nextDouble();

			System.out.print("体重(kg)：");
			double inputWeight = scan.nextDouble();

			Bmi result = new Bmi(inputHeight, inputWeight);
			double resultBmi = result.getBmi(inputHeight, inputWeight);
			System.out.println("BMI：" + resultBmi);

			System.out.println();

			if(resultBmi < 18.5) {
				System.out.println("評価：低体重");

			}else if(resultBmi < 25) {
				System.out.println("評価：普通体重");

			}else {
				System.out.println("評価：肥満");
			}

		}catch(Exception e) {
			System.out.println("\nやり直せ");
		}
	}
}

class Bmi{
	public double weight;
	public double height;

	public Bmi(double height, double weight) {
		this.height = height;
		this.weight = weight;
	}

	public double getBmi(double height, double weight) {
		return weight / (height * height);
	}
}
```

```実行結果.
身長(m)：1.7　←自分で入力
体重(kg)：60　←自分で入力
BMI：20.761245674740486

評価：普通体重
```


#どうですかね??
おかしなところあれば、(優しい)コメントください。

個人的には、「double height」とかが何回も出てくるのが気にくわないですｗ

#マネするべきソースコード
以下は、@shiracamus　さんが書いてくれたソースコードになります。
こちらを参考にしてみてください。

ポイントは下記の通り
1.クラス名は直感的にみて分かりやすく命名する
2.インスタンス変数を理解し、コードが冗長にならないようにする

```HealthChecker.java
import java.util.Scanner;

public class HealthChecker {
    public static void main(String[] args) {
        try {
            @SuppressWarnings("resource")
            Scanner scan = new Scanner(System.in);
            System.out.print("身長(m)：");
            var height = scan.nextDouble();
            System.out.print("体重(kg)：");
            var weight = scan.nextDouble();

            var body = new Body(height, weight);
            System.out.println("BMI：" + body.bmi());
            System.out.println();
            System.out.println("評価:" + body.style());
        } catch (Exception e) {
            System.out.println("\nやり直せ");
        }
    }
}

class Body {
    final public double weight;
    final public double height;

    public Body(double height, double weight) {
        this.height = height;
        this.weight = weight;
    }

    public double bmi() {
        return weight / (height * height);
    }

    public String style() {
        var bmi = bmi();
        if (bmi < 18.5) {
            return "低体重";
        } else if (bmi < 25) {
             return "普通体重";
        } else {
             return "肥満";
        }
    }
}

```

#感想
コードを見ればわかる通り、圧倒的に美しいですね。
僕のソースコード(Test1.java)では、「height」と「weight」何回出てくるんだよって感じｗ

やっぱり、先輩プログラマーに見ていただけるのはとても貴重だなと感じました。一人でやっていると、
「エラーがでてないからＯＫ」と思い、どうしても脳死になりがちです。。。
情報発信系のサイトの使い方としては、間違ってるかもしれませんが、あと半年(いや、1年)ほど
お付き合いいただければ幸いです。
AWS 認定 ソリューションアーキテクト – アソシエイト(SAA)取得のための勉強方法

# はじめに
AWS認定クラウドプラクティショナー(CLF)を取得した後、約5か月間の勉強期間を経てSAAを取得しました。
本記事ではSAA取得のために行った勉強方法を共有いたします。

# SAAの勉強方法
以下の本をテキストとして使用しました。当時は初版でしたが、改訂版が出ていますので、そのリンクを張っておきます。

https://www.amazon.co.jp/dp/4815607389

問題も掲載されていますが、初級(CLF)受験時に問題演習不足を実感したため、別途問題集を使用しました。当時は2019年版でした。

https://www.amazon.co.jp/dp/B08DC9ZWQX

この問題集は解説が明快で、著者（Neal Davis）がAWSについて深く理解していることが実感できました。私が使用したのはペーパーバック版で、線を引く、ネットで調べた内容を書き込むといった使い方をしました。
余談ですが、青の油性ボールペンが使いやすいです。AWSのサービス名を白紙に書いて覚える、図にまとめる、テキストに線を引く等、全て1本でまかなえます。黒や赤のボールペンも試してみましたが、黒はテキストの文字色と区別がつきにくく、赤は色が強すぎると感じたため、青に落ち着きました。

# 試験本番
試験準備で多めに問題演習をしたため、実際の試験では自信をもって解答することができました。初級(CLF)と同様、SAAもあまり問題文が長くないため、時間的にも余裕がありました。
結果は合格で、試験後すぐに上級(SAP)の試験準備を開始しました。

https://qiita.com/pti/items/c1930ccd8b0b91a780ea
PL-900振り返り～OnVUE受験のこととか出た問題とか～

#試験結果
オラ合格したぞ！
得点は863(合格点700)でスカウターぶっ壊れるかと思ったぞ！

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461645/53c22cdd-5c37-3f1a-3aaf-331719f0c3ae.png)|
|:-:|

満遍なく網羅できてるな！ヨシッ！
ん？でもおめぇ満点のセクションねーじゃねぇか。

#受験方法
ピアソンのOnVUEというオンライン試験で家のPCから受験したぞ。
家での受験？カンニングし放題や！とおもったおめぇ・・・オラ失望したぞ！
OnVUEではカンニング対策もバッチリだから諦めて勉強しろ！

OnVUEはウェブカメラとマイクのついたPCが必要そうだからそこは気をつけろ！

受験料は、事前に「Microsoft Power Platform Virtual Training Day: Fundamentals」っちゅう無料のオンラインセミナーを受けてバウチャーもらってたからタダだったぞ。おめぇらも早く申し込んどけ！
オラが思うに、Microsoftとしては、PL-900は入門的な位置づけでとりあえずPower Platform人口を増やしたいという思惑で、この試験でお金稼ごうなんて気はねぇようだ。プラットフォームを浸透させたらあとは勝手に儲けられるからな！さすがMS汚い！

**申し込み**
「Microsoft Power Platform Virtual Training Day: Fundamentals」受講後、メールが届いてそんなかのリンクからピアソンで受験予約ができっぞ！
上でも書いたとおり、オラはOnVUEっちゅう自宅からのオンライン受験を選択したぞ！

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461645/885675df-e503-6f46-1771-a1267439886f.png)|
|:-:|

OnVUEに申し込んだらシステムテストをやれって言われるから、受験までに受験予定のPCでテストツールを動かしてちゃんとテスト受けれるPC環境かどうかチェックするんだ！

**受験の準備**
部屋の片付け。これが今回の受験で一番苦労したポイントだ。部屋がきたねーやつは気ぃつけろ！
机の上には受験するPC以外置かないようにしとけ！

**受験日当日**
まずは受験予約メールに書いてあるリンクからチェックインだ！
チェックインは受験予定時刻の30分前からできっから余裕持ってやっとけ！

チェックインしたらシステムテストで使ったツールと同じやつをまたインストールしろって言われんだ！
ツール進めてくと、電話番号を入れろって言われるから、国番号から入れてけ！
日本の場合、かつ、スマホ（携帯電話）の場合は「81 90XXXXXXXX」みたいな感じだ！090じゃなくて90だぞ！

ちょっと待つと、スマホにメッセージが届くからその中のリンクを開くんだ！
リンク先のサイトで、自分の顔、身分証明書、部屋を四方から撮ってアップロードしろって言われるから素直に従うんだ！

アップロードが完了したらPCのツールを進めるんだ！確かこのタイミングでWebカメラとマイクが音になって試験監の監視が始まるぞ！
試験監督の人からチャットがきて、PCを持ち上げてゆっくり回して部屋を360度映せとか、受験PCがおいてある机の周りを映せとか言われっぞ！
オラの場合は部屋にPCとは別にテレビがあって、それに布かけろとか言われたぞ！布はなかったから寝床から毛布引っ張ってきてかぶせたぞ！

その後、試験開始していいか聞かれるから「はい、大丈夫です。お願いします。」ってちゃんと答えような！
画面が試験の注意事項に切り替わって、他のアプリの操作とかはできなくなるぞ！
オラはここで注意事項を独り言で読み上げてたんだが、試験管からチャットが飛んできて、受験中しゃべるのは違反だから不合格になるから注意しろって言われたぞ！
注意事項を読み終わったら試験に移れるぞ！試験時刻まで待つ必要はないぞ！

上でも書いたとおり、試験が始まるとツールが全面になってテスト以外のアプリは操作できなくなるんだ！というか普通のWindowsの操作自体に戻れなくなる！オラは試験中不具合があってどうしたらいいかチャットで聞いたら、電源長押ししてPC再起動しろって言われたぞ！
再起動後に試験再開するときは最初からの流れをたどったけど、写真のアップロードとかはすでに終わってる状態で、すぐに試験に戻れたぞ！

受験後すぐにスコアが表示されっからドキドキだ！

#出た問題
思い出せる範囲で、どんな感じの問題が出たか書いてくぞ！ #番号がExamTopicsの問題番号だ！
記憶が曖昧だから似てるけど詳細は違うってのもあるかもしれねーけどそこは簡便な！

https://www.examtopics.com/exams/microsoft/pl-900/view/

\#2
\#13
\#20
\#27
\#28
\#31
\#34
\#36
\#49
\#52
\#53
\#55
\#59
\#61
\#64
\#66
\#68
\#73
\#76
\#80
\#84
\#85
\#100
\#101
\#105
\#106

#さいごに
試験は満遍なく出た気がするぞ！
ExamTopicsとか類似サイトの問題がそのまま出るパターンも多いからとりあえず日本語翻訳しながらやってみるといいぞ！
ただ、ページ切り替えのたびに画像判定させられてイラッとするぞ！あと普通に答え間違ってるやつとかあるから注意な！
AutoHotKeyのGUIからSteamゲームを選択してGame起動する。

## AutoHotkeyを用いてSteamゲーム起動選択を実現する。
基本的には、デスクトップ上にあるショートカットファイルからゲームを起動するのだが、デスクトップを表示させるのがめんどくさい。
遊びたいゲームが複数ある場合は、探すのもおっくうになるほど管理が大変になる。

何とかして楽ができないか考えた。

ということで、表題通り、GUIからゲームを選び、そこから目的のゲームを起動する方法をとる。
一見めんどくさそうに思うのだが、GUI起動をショートカットキーに割り当てておけば、デスクトップを表示させることもなく、そこから選ぶこともなく、いつでも呼び出せるという点が異なる。

![GUI画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425551/b9d5d1b0-0f13-288f-47de-65d96f8adae3.png)

何より、ゲーム起動時のショートカットキーは、ゲームの頭文字に割り当てるため、簡単に無意識下で呼び出せるのも少ない労力になることだろう。
そう思ったのだが、常駐させないため、必ず最低でも1度はデスクトップなりどこかなりのエクスプローラを表示させる必要があり、そして今回のプログラムを起動させる作業が発生する。

1行登録のみの場合は、GUIを表示せず、直接ゲーム起動できるようにしたため、利便性は向上したはず。





















### プログラミング部分
解説するまでもないことだが、、、
AutoHotkeyを使い、デスクトップ上にあるショートカットファイルをもとにGUIを生成し、そのGUIから人間様が目的のゲームを選択し、そしてOKボタン押下により、晴れてGame Play!!
当たり前だが、ショートカットファイルの作成やその登録などは手作業で行う。

Game起動後は、本プログラムが終了する。
























#### 基本的に
一応は、[Github](https://github.com/asakunotomohiro/Launch2steam4autoHotKey)のReadme.mdに解説を書いている。





















#### Pathの書き換え方法。
見栄えの問題として、配列にショートカットファイルを記述する場合、空行を付けることにしている。

```common-lisp:抜粋.ahk
GameArray := [	; ここが1行目の空行
		 , A_Desktop . "\[ゲーム用ショートカットファイル名].url"	; ここが2行目
		 , A_Desktop . "\Flockers.url"	; 3行目。
		 , ""]	; 4行目も空行。
```

境界値テストを厳密にやっていないため、1行目にショートカットファイルを記述した場合、読み込まないかもしれない。
また、存在しないショートカットファイルを記述した場合、GUIに反映させていない。



![ファイル不在は非表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425551/7ef8b659-6cd5-4547-2438-ec9f4f391769.png)



















#### 呼び出し方法
関数の使い方。

以下、例。

```scheme:AutoHotKey.ahk
; 下記、F1とoキーの組み合わせで起動する。
F1 & o::
	; 以下、配列(ここに起動したいゲームのショートカットファイルを指定する。
	GameArray := [ ; ここは空行
			 , A_Desktop . "\Oxygen Not Included.url"
			 , A_Desktop . "\OpenTTD.url"
			 , ""] ; ここも空行(どちらも見栄えのため)

	; 上記配列を第1引数に渡す。
	Launch2steam4autoHotKey( GameArray )
return
```

AutoHotkeyでの起動方法は、`F1 & o::`であれば、F1キーとoキーの組み合わせでゲーム起動用GUIが立ち上がる。
配列(`GameArray`)には立ち上げたいゲームのショートカットファイル名を記載すればいい。
プログラムを少し改良し、exeファイルやURLの記述も対応した。
上記例は、デスクトップ上に置いているため、[組み込み変数](http://ahkwiki.net/Variables)の`A_Desktop`を使っているだけで、Pathをそのまま記載しても動く。
その後は呼び出し。
`Launch2steam4autoHotKey`関数に、作成した配列を第1引数に渡すだけ。
冒頭通り、1行記述をした場合、GUIを表示せず、直接ゲームが起動する(本プログラム常駐)。
しかし、1行のみの場合の指定は、ショートカットファイルかURLのどちらかに限る。

あとは起動ショートカットキーで呼び出すだけ(上記例で言えば、`F1 & o`)。

これでゲーム生活が快適になればお慰み。



















### AutoHotKeyそのもの
基本的に、今までの派遣先は、実行させる許可を出してくれなかった。
何が原因かわからないが、`Ctrl+h`でバックスペースキーにできないのはストレスになるため、結構つらいのだが、御上の決定を覆すだけの発言権がないため、文字を消すときは必ず躓くことになるという・・・。
その仕組みを入れていたのだが、改良後は、削除した(常駐させないために)。

そもそもネットワークから隔離された場所で有名なのは金融系の現場で、その場合はどうしようもない。
ドコモの開発現場もそうだった。
キーボードの持ち込みもできないため、間違った記号配置のキーボードを押しつけられて静かに憤ったよ(ただの派遣社員があらがうすべ無し)。
そして、その現場のNEC女性は、休日出勤指示を私事で出してくるほどこき使ってくる。
拒否したら私の映画鑑賞についてくるとか私の私生活にまで踏み込んで権限乱用して派遣社員を見下してきた。
腹立って仕方なかった。
全部拒否したけど。
くっそぉ～。

また、テキストエディタの導入も拒む現場がある。
何の理由で嫌がるのか全く分からない(現場リーダが客に許可を求める必要があったから？)。

以上。
tp-link製AC1300 USB Wi-Fi子機をRaspberryPi(busters)で使う

#はじめに

RaspberryPi2で5GHz-WiFiに接続しようと思い、事前の雑な調査でlinuxでさくっと使えそうに見えたtp-linkのAC1300(T4U Plus)というWi-Fi子機を購入した。ところが、実際にはドライバ導入に難儀してしまった。導入までのメモを記す。

#使用チップに諸説あり？
T4U Plusのチップとして、rtl8812au/rtl8814auを使っているという記述やrtl8822buを使っているという記述があり、非常に混乱してドライバ導入に手間取ってしまった。私の購入した表題の商品(アンテナが2本ついていてUSB3.0に接続できるもの)は、rtl8822buのドライバが正解だった。

#ドライバの導入方法

基本的にはこちらに書いてある通りに行うが、一応自分で行った手順を記す。
https://gist.github.com/primaryobjects/f723b966d5f42094619f9c1048c7838b

```
$ sudo apt install dkms
$ git clone https://github.com/Mephysto666/rtl8822bu
$ cd rtl8822bu/
$ vi Makefile
$ sudo dkms add .
$ sudo dkms install -m 88x2bu -v 1.1
```

環境によっては、ドライバ構築に必要なパッケージを更に追加でインストールする必要があるかもしれない(コンパイル関係のツールやカーネルヘッダファイル等。私の環境で追加が必要だったのはdkmsのみ)。また、今回はRaspberryPi用にドライバをビルドするため、Makefileを以下のように変更する。未変更のままdkms installすると、コンパイルエラーで先に進まない。PC環境では変更の必要はないと思う(未確認)。

変更前のMakefile(抜粋):

```
###################### Platform Related #######################
CONFIG_PLATFORM_I386_PC = y
CONFIG_PLATFORM_ARM_RPI = n
```

変更後のMakefile(抜粋):

```
###################### Platform Related #######################
CONFIG_PLATFORM_I386_PC = n
CONFIG_PLATFORM_ARM_RPI = y
```

導入後はRaspberryPiを再起動して動作を確認する。再起動後に子機をUSBポートに接続すると、子機の緑のLEDがチカチカするようになった。STAモードで5GHz-APに接続した際のiwconfigの出力は以下のようになった。5GHzで接続されていることがわかる。

```
wlan0     IEEE 802.11AC  ESSID:"XXXXXXXXXXXX-XX"  Nickname:"<WIFI@REALTEK>"
          Mode:Managed  Frequency:5.26 GHz  Access Point: XX:XX:XX:XX:XX:XX
          Bit Rate:867 Mb/s   Sensitivity:0/0
          Retry:off   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality=89/100  Signal level=35/100  Noise level=0/100
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0
```

#最後に

とりあえずドライバは導入することができたが、動作の安定性や実際の通信速度等は適宜確認する必要がある。ドライバをdkmsに登録したのでカーネル更新とドライバ更新は連動するはず(dkmsの仕組は知らなかった)。
Laravel6 論理削除

ほ〜と思ったことがあったので共有。

#物理削除と論理削除
ユーザーのデータを削除したい時。
表題の2つの方法があるみたいです。

`物理削除`は実際にSQLでDeleteを実行し、データベースから削除される。
なので復元したり削除されたデータを参照することはできない。

`論理削除`は実際にはデータを削除せずに、削除しているかのように振る舞うことです。
消されたフリをしているだけなので復元すぐできるし参照もできるのです。

↓論理削除Laravelでは簡単にできるようです。

##論理削除用カラム追加

```[database/migrations/yyyy_mm_dd_000000_create_users_table.php]※一部抜粋
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            // 省略
            $table->softDeletes();
        });
    }
```

`$table->softDeletes()`で「delete_at」というカラムが作成されます。
↓続いてモデルをいじります。

```app/User.php
use Illuminate\Database\Eloquent\SoftDeletes;
// 省略
class User extends Authenticatable implements MustVerifyEmail
{
    // 省略
    use SoftDeletes; // 追加
    // 省略
```

これだけで、今回の場合Userモデル関連のdelete()を行うと「delete_at」カラムに日付が入力されて論理削除になる！

ただしやみくもに論理削除を設計に組み込むと
論理削除データが多い場合データ量増大やそれに伴う検索性能の劣化する可能性があるため
あまりよろしくない。

#まとめ
現段階ではこの２つを使いこなすのは到底難しいけども
概念として知っておくべきだと思ったのでメモしておきました。

間違ってること言ってるかもしれないので鵜呑みは要注意。
Railsをガイドに沿って基礎から学ぶ①

<h1>はじめに</h1>
この記事はスキルアップを目的とした記録です。
前回に意味の分からないログイン画面を作成する投稿をしたところ、基礎知識が足りていないと感じたのでガイドに沿って1から勉強をしなおすことにしました。
現時点(2021/06/12)の物です。
わからない部分に関しては今後更新していきます。

<h1>１．教材</h1>
今回はRailsガイドを参考にしました。

https://railsguides.jp/getting_started.html

今回はHello Railsを表示するまでの手順を記述し、ガイドを見て理解ができなかったところを深堀してお伝えしたいと思います。

<h1>２．Railsとは</h1>
①RailsとはRuby言語のフレームワーク
②Webアプリケーション簡単に設計出来るようになっている
③同一コードを繰り返さない事を推奨している
④<font color="red">設定よりも規約が優先される</font>

<h1>３．新規プロジェクトの作成</h1>

<h3>３．１Railsのインストール</h3>
環境構築手順については以前投稿しているので割愛します。

https://qiita.com/HybridKotaro/items/8f71a65e3b913307cda0

<h3>３-２.新規アプリケーション作成</h3>
環境構築が終了したら新しいアプリケーションを生成します。
今回もCドライブ直下にアプリケーションを置きます。

```
$cd C:\
$rails new blog
```

生成が完了したらアプリケーションの中身を見ていきます。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1600683/71b177d1-54ec-2038-bac5-63f86663b1b5.png">

上から初心者でも必要そうなものを紹介
<h4>①app/</h4>
アプリケーションの構成に重要になるフォルダ。
<font color="red">MVCモデル</font>に沿って作られている。
MVCモデルを知らない人は先にそちらを調べたほうが学習しやすいかもしれません。
<h4>②config/</h4>
アプリケーションの設定ファイルが置いている。
<font color="red">使用頻度が高く重要。</font>
気になる方はこちらのガイドから学ぶとよいと思います。
https://railsguides.jp/configuring.html
<h4>③db/</h4>
データベーススキーマ、データベースマイグレーションファイルが置かれる場所。
<font color="red">appで記述しているModelと強いかかわりがあります</font>
<h4>④public/</h4>
外部からも接続できる範囲で、直接参照できるフォルダ。

<h1>Hello,Rails</h1>
<h3>４．１Webサーバーの起動</h3>

おさらい的な感じ
サーバーを起動します。

```
$rails s
```

<h3>４．２画面にHelloを表示する</h3>
Railsを画面上で表示するには、最低限<font color="red">Controller</font>と<font color="red">View</font>が必要。
更に<font color="red">ルーティング</font>の設定も必要になります。

まずはURLと画面を紐づけるためにルーティングを設定します。

```rb:~/blog/config/routes.rb
Rails.application.routes.draw do
  get "/articles" , to: "articles#index"
end
```

get "対象URL名" , to: "コントローラー名#アクション名"を追加しています。
<font color="red">get</font>はHTTPメソッドを指定しています。
<font color="red">to:</font>は"コントローラー名#アクション名"でコントローラーとビューの紐づけを行います。

るーていんぐの設定が完了したら次はコントローラーを生成します。

```
$rails generate controller Articles
```
<font color="red">※コントローラー名は原則複数形で定義します。今回はArticleの複数形Articlesです。２．Railsとはで紹介した規約の一部になります</font>

生成が完了したら中身生成したコントローラーを確認して、アクションメソッド(index)を定義してあげましょう。
<font color="red">※アクションメソッドとはルーティングにより指定されるときの名前です</font>

```rb:blog/app/controller/articles_controller.rb
class ArticlesController < ApplicationController
    def index
    end
end
```

次に画面表示のビューファイルを作って、中身を記述します。

```erb:~blog\app\views\articles\index.html.erb
<h1>Hello, Rails</h1>
```

ControllerとViewを設定した時点で、routes.rbで定義した

```rb:~/blog/config/routes.rb
get "/articles", to: "articles#index"
```
でURLとコントローラーのアクション名とビューのファイルが紐づきます。
実際にアクセスすると下のようになります。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1600683/f846c25d-761b-9526-168f-6a35523cd82a.png">

<h3>４．３アプリケーションのHomeを設定する</h3>
http://localhost:3000 で開いてもArticlesに遷移させる方法があります。
config/routes.rbを開き、rootを追加します。

```rb:~/blog/config/routes.rb
get "/articles", to: "articles#index"
```

設定後に http://localhost:3000 を開くと、元々表示されていた画面がArticlesに変更されています。

<h1>さいごに</h1>
最後まで閲覧ありがとうございました。
記録として投稿しているため、間違っている部分や嘘をついている部分があるかもしれません。
もしお気づきの点がございましたらコメント等で教えてください。
今後もガイドに沿って理解を深めていこうと思います。
Nginx×Django(gunicorn)×PostgreSQLのWEBアプリケーションをAWS EC2上にデプロイするための前提知識

# 最初にWEBアプリケーションのおさらい
### WEBアプリケーションの構成
WEBアプリケーションは主に、

**・WEBサーバー**
**・アプリケーションサーバー**
**・DBサーバー**

これらが組み合わさって完成します。このサーバーって言葉が分かりづらいですよね。
サーバーは主に以下の2つの言い回しがあるようです。

**・コンピュータとしてのサーバ**
**・ソフトウェアとしてのサーバ(ミドルウェア)**

![qiita1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961267/bbd01603-5358-3e23-fbaf-6e403a3e164a.jpeg)


画面のない処理専用のPCをサーバーといったりしますが、あれはコンピュータとしてのサーバですね。
あと、VPS（Virtual Private Server）というサービスの名前の中にも、サーバーという単語が使われています。VPSは仮想サーバーをレンタルするサービスですが、これもコンピュータとしてのサーバーですね。

そして、今回構築していくWEBサーバやアプリケーションサーバ、DBサーバは、OSの上にミドルウェアとして構築していく、ソフトウェアとしてのサーバです。このようなミドルウェアには、他にもファイルサーバやメールサーバがあります。

ちなみに、一番上の層の"アプリケーション"というのは、パソコン上で機能を使えるようにしたものです。ChromeとかPowerPointとか。このアプリケーションはスマホアプリやデスクトップアプリといった意味合いが強くて、WEBアプリケーションとは違う意味なんですよね。ややこしい。

長々と書きましたが、WEBアプリケーションの構築は、WEBサーバ、アプリケーションサーバ、DBサーバの3つのミドルウェア部分を構築して、連携させていくようなイメージになります。

# WEBアプケーション構成手順
・WEBサーバー　→ Nginx
・アプリケーションサーバー → Django(gunicorn)
・DBサーバー　→ PostgreSQL

それぞれのサーバには、上記のツール・サービスを使っていきます。今回はこれらをAWS EC2上に構成していきます。

順番的には、
**・PostgreSQLをスタートさせる**
→ DBサーバーが立ち上がります
**・gunicornを起動する**
→ Djangoフレームワークがアプリケーションサーバーとして立ち上がります。Djangoでいい感じに設定しておくと、DBサーバーと紐付けされます。
**・Nginxを起動させる**
→ WEBサーバーが立ち上がります。あらかじめ設定ファイルにいい感じに記述すると、アプリケーションサーバーと紐付けされます。

####gunicornについて
Djangoフレームワークは、WSGIという仕様に則って開発されています。
これをアプリケーションサーバとして動作させることができるのが、
・gunicorn
・uwsgi
といったものになります。今回は、uwsgiではなくgunicornを使っていきます。

![スクリーンショット 2021-06-12 23.57.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961267/2f0e14d9-9ddc-758e-d395-bdeddc535381.jpeg)
Talendを使う前に知っておきたいこと

# 目的
Talendでジョブを作成〜実行までの流れを大雑把に把握したい。

# Talendとは
- ETL製品で様々なデータを統合・連携するためのツールを提供しています。
- Talend Open StudioというGUIベースのツールでデータ連携などのジョブを作成できます。
- 作成したジョブはJavaアプリのためJVM上で実行可能です。

参考：https://www.talend.com/jp/

# ジョブ作成から実行までの流れ
以下の処理を行うジョブを作成する前提で記載していきます。　※使用ツールは無償版です。

1. クラウドサービスからCSVを取得
1. CSVのデータを加工
1. 加工済みデータをDBに登録

### 全体の流れ
ローカル環境でジョブを作成し、作成したジョブを実行したい環境に配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635116/648a309b-0049-27e3-6e10-735b267c6a95.png)

### ジョブの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635116/39d8d84d-eee3-2189-e2d5-d1f5eec1d209.png)

**GUIベースでジョブの作成ができます。**
eclipseをベースにしているので開発者にとっては馴染みやすそうです。
※GUIのイメージは[こちらの記事](https://qiita.com/airkoda/items/a837d3c5d851d98d2612)をどうぞ

**クラウドサービス(AWSなど)やDBへの接続情報をGUI上で設定できます。**
設定用のコンポーネント(部品)もTalend側でいくつか用意されているのでスムーズに設定が可能です。

**外部で作成した処理(jarファイル)を取り込むこともできます。**
マッピングなどの単純な処理はTalend上で作成し、
複雑な処理などは他の環境・ツールで作成したjarファイルを取り込むことで、
Talend上で作成しなくて済みます。

**ローカル環境でもジョブの実行ができます。**
開発環境として動作検証などに利用することもできます。

**作成したジョブをjar形式で出力できます。**
ジョブの配置でも説明しますが、jarが読み込める環境であればどこでも起動させることができます。

### ジョブの配置
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635116/6aa6cb77-a341-c2bf-6ab2-4403be7cee86.png)

**実行環境の必須条件**
サーバ上にJVMが導入されていること。
クラウドサービスやDBなどにアクセスできるネットワークに所属していること。

**実行方法**
ジョブ管理ツールに配置したjarファイルを読み込ませることでスケジュール起動やログ監視などが可能です。
クラウドサービス(AWSのLambdaなど)上に配置することでもジョブの実行が可能です。
また、cronやタスクスケジューラから直接プログラム(jar)を叩くこともできなくはないです。（非推奨）

# Talend有償版
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635116/e5778b97-561d-5425-741c-42fd512f0483.png)

有償版のTalendだと以下2つの環境が提供されるそうです。

**運用管理サーバ**
複数人でのジョブ作成の管理・同期を行えます。
また、無償版では手動で行っていたジョブ実行サーバへのジョブの配置・展開やスケジューリングを
運用管理サーバを通じて実施することができます。

**ジョブ実行サーバ**
ジョブ実行サーバが複数台提供されるため、ジョブの並列実行を行えます。
更に仮想化することでロードバランシングや自動フェールオーバなども可能になります。

# まとめ
ジョブ作成〜実行までの大雑把な流れは把握できたかと思います。

ジョブ作成後の流れはeclipseでJAVAのプログラムを作成する時と同じなので、
開発者であればイメージはしやすいかと。

既存でジョブ管理ツールを導入していれば、そこに相乗りさせるのもありかと。

# 参考

- https://www.gixo.jp/blog/6667/
android エミュレーター Navigation is blocked

version
flutter: 1.22.4
sign_in_with_apple: 3.0.0

[Flutter・Firebase で Android アプリの Sign in with Apple 対応をする🎯🔥🤖🍎](https://medium.com/flutter-jp/sign-in-with-apple-d0d123cbbe17)
を参考にApple認可サーバーからリダイレクトされるページを自作したところ、以下のエラーがでました。

```
Navigation is blocked: intent://callback?
code=example&id_token=example
#Intent;package=example;scheme=signinwithapple;end
```

原因としては、Android System WebViewのバージョンが低く、リダイレクトうまくできなかったようです。

解決方法としましては、play storeが使用できるandroidエミュレーターを使用し、
[Android System WebView](https://play.google.com/store/apps/details?id=com.google.android.webview&hl=ja&gl=US)
をアップデートすると、エラーは解消されました。
残プロ　第-11回　~ラズパイに朝礼を教え込む~

# 孤独という伝染病

プログラマーとは孤独なものです．ひたすらにコードと向き合い，読み，書き，苦悩する．


毎朝早くに通勤(または通学)し，夜遅くまで大量のコードを編集．疲労困憊で帰路につき信号の赤にふと足を止めた瞬間，

　**「あの条件処理してない」**

頭をよぎるエラーコード...

現代社会がかかえる『孤独という病』をプログラマーは生来，背負って生きています．責任の所在がはっきりするプログラミングという世界において，我々を支えているのは常に**自分**と**エラーに対する不安**だけです．仕事で疲れた体を労ってくれるパートナー，今日一日の出来事を楽しそうに喋ってくれる可愛い娘がいたとしても，頭を支配するのは数百行のエラーコード．

まして，そんな恵まれた環境すら築けていない私のような人間に残された孤独への(ささやかな)抵抗は，**RaspberryPiを人格化**することでした.


# RaspberryPiとかいう生意気な後輩

RaspberryPi(通称ラズパイ)をご存知ですか？科学教育や産業，研究に利用されたりと多岐にわたる分野で活躍しているシングルボードコンピュータです．

あなたがプログラミングや電子工作に興味をお持ちなら，自分用のラズパイが１つぐらい家にあるでしょう．ここで，少し思い出してほしいのですが，最初のラズパイを購入し初めて触れた時，どのような感情を抱きましたか？きっと「こんなに小さいのに賢くて偉い」という**愛情**や，「これで色んなことができるぞ」といった**将来に対する希望**を見出したのではないでしょうか．

では，果たして現在もあの時と同じ感情といえますか？きっとラズパイができること，できないこと，様々な制約を知り，**失望**や**怒り**が湧いた方が少なくないと思います．あの頃RaspberryPiに対して向けていた**『娘に対する愛情』**は，今や**『生意気な後輩に対する苛立ち』**へと変化しました．

### RaspberryPiの寿命

ラズパイは短く見積もるとおおよそ2年ほどで寿命を迎えるようです(大抵はSDカードの方が先に逝きますが)．私が今回使用するラズパイは，半年ほど前に購入したもので，**生後6カ月**と言ってもいいでしょう．

これ，人間の年齢に換算すると20歳前後なんですよね．高校卒業したての生意気な後輩って年．購入後3カ月とかなるともう社会も知らないクソガキってレベル．人生の先輩として**年上への敬意**を教えてやる必要がありますね...


# 挨拶のできる後輩へ

後輩としてまず身に着けるべきは気持ちのいい挨拶でしょう．


~~~hello.py
message = ("おはようございます！！")
print(message)
~~~


ラズパイを教育するには，**直接指導する**($ python3 hello.py)方法と，**脳に叩き込む**(crontab -e)方法があります．毎度指導するのも面倒なので，今回は後輩君の**脳内に直接書き込みましょう**．


~~~ raspberrypi:terminal
$ crontab -e
~~~


~~~ cron:cron
0 7 * * * python3 /home/pi/Documents/hello.py
# 書き方は[分　時　日　月　年　コマンド]
~~~


~~~ raspberrypi:terminal
おはようございます！！
~~~


これで後輩君は毎朝7時に挨拶できるようになりました．


# 意味のある朝礼を

毎朝おはようと言われても鬱陶しいだけなので，**朝礼の内容**を決めましょう．今回は，

- その日の天気・温度
- 直近の予定
- 新型コロナウイルス感染者数の変化

を報告してもらいます．
また，朝礼は**リモート**で行ってもらいましょう．

これらの実装には[webスクレイピング](https://qiita.com/R1nY1x1/items/a02651ad7d4644d44b2e#%E7%B0%A1%E5%8D%98%E3%81%AB%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0%E3%82%92%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)，[csv操作](https://qiita.com/R1nY1x1/items/4b35cd0e64ed45cf1244#%E3%82%BF%E3%82%B9%E3%82%AF%E7%AE%A1%E7%90%86%E7%94%A8%E3%81%AB%E7%B5%84%E3%81%BF%E8%BE%BC%E3%81%BF)，[matplotlibでのグラフ作成](https://qiita.com/R1nY1x1/items/a02651ad7d4644d44b2e#%E8%A1%A8%E3%82%92%E6%8F%8F%E7%94%BB%E3%81%97%E7%94%BB%E5%83%8F%E5%8C%96)，[LineNotifyでの通知](https://qiita.com/R1nY1x1/items/ef444ea809a8061e8adc#python%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)を利用しています．それぞれ，かなり簡素ではありますが解説をしているので，興味ある方はご覧になってください．


# やればできる子，後輩君

ここまでできれば上出来でしょう！
これで鬱屈な朝を後輩君の気持ちいい朝礼とともに迎えられます！

![kohai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578927/e8227f90-780c-bf88-6dc5-8b8b67101200.png)