OmniAICreator/Qiita-1.07M huggingface dataset:
Laravel5.8でマルチ認証を実装する（参考記事の補足）

<h1>Laravel5.8でマルチ認証を実装する（参考記事の補足）</h1>
Laravel5.8でのマルチ認証の大枠の実装に関してはこちらの記事を参考にしました。

https://webxreal.com/laravel-multi-auth/

しかし、記事にもいくつか修正すべき点が見受けられたので、忘備録も兼ねてまとめます。

<h2>【補足１】ルーティングはどのように記述すればいいの？ </h2>

記事の方ではこのように書かれています。

```routes/web.php
/** 以下追加 **/
// Admin
Route::group(['prefix' => 'admin'], function(){
    // AdminHome
    Route::get('home', 'Admin\HomeController@index')->name('admin.home');
    //login&logout
    Route::get('login', 'Admin\LoginController@showLoginForm')->name('admin.login');
    Route::post('login', 'Admin\LoginController@login')->name('admin.login');
    Route::post('logout', 'Admin\LoginController@logout')->name('admin.logout');
});
/** ここまで **/
```
`Route::group(['prefix' => 'admin']`としているだけで、肝心のmiddlewareに関する部分が抜けています。
なので、下記のように修正が必要です。

```routes/web.php
// 'middleware'=>'auth:admin'を追加
Route::group(['prefix' => 'admin', 'middleware'=>'auth:admin'], function(){
    
    //管理者ログインしたユーザーのみアクセス可能にしたいルーティングを記述
    Route::get('home', 'Admin\HomeController@index')->name('admin.home');

});

//ログインやログアウト後のページに関しては、非ログイン時にアクセスするので'middleware'=>'auth:admin'の外に記述する
Route::get('admin/login', 'Admin\LoginController@showLoginForm')->name('admin_login');
Route::post('admin/login', 'Admin\LoginController@login')->name('admin_login');
Route::post('admin/logout', 'Admin\LoginController@logout')->name('admin_logout');

```

要点は以下２点。
・ログイン後のみアクセス許可したいページは`'middleware'=>'auth:admin'`をgroupで囲む
・ログインやログアウト後のページに関しては、非ログイン時にアクセスするので`'middleware'=>'auth:admin'`の外に記述する

<h2>【補足２】 管理者ログイン情報取得 正しくは、、、</h2>
<p>管理者マイページにログイン中の管理者情報を取得する場合、記事だと以下のように書かれています。</p>

```xxxController.php
use Illuminate\Support\Facades\Auth;

$admin = Auth::user();
$admin->id;
$admin->name;
```

<p>しかしこれだと、当然、通常ログイン中のユーザー情報が取得されてしまいます。<br>そこで下記のように修正が必要になります。</p>

```xxxController.php
use Illuminate\Support\Facades\Auth;

$admin = Auth::guard('admin')->user(); //ログイン中の管理者情報を取得
$admin->id;
$admin->name;
```
guardとは何なのかについてはこちらの記事で解説されています。

https://qiita.com/tomoeine/items/40a966bf3801633cf90f

要は、config/auth.phpで

```config/auth.php
    'guards' => [
        'user' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
    ],
```

と、adminをguardsに設定しているので、`guard('admin')`が使えるという事です。



より実践的な説明として、参考に例を挙げます。
管理者マイページにログイン中の管理者情報を表示したい場合、以下の通りになります。

```ProfileController.php
namespace App\Http\Controllers\Admin; //必要。念の為これも補足。
use Illuminate\Support\Facades\Auth;

    public function mypage()
    {
        $admin = Auth::guard('admin')->user(); 
        return view('admin.profile.mypage',['admin' => $admin]);
    }
```
こんな具合になります。<br>そして、mypage.blade.phpで`{{ $admin->name }}`とすればnameが取得できます。
JavaScropt [初心者の備忘録] テキストボックスに入力した数字で加減するカウンター

[やりたかったこと]
テキストボックスを作成し、そこに入力された数値に対して、
プラスまたはマイナスボタンをクリックすると、その分だけ加算または減算されるだけのもの。


```HTML
<div class="spinner_area">
      <p id="counter" type="number">0</p>
      <input type="button" value="＋" class="btnspinner" data-cal="1" data-target=".counter1" id="up" hovercolor="red">
      <input type="number" value="1" class="counter1" data-max="500" data-min="0" id="textbox">
      <input type="button" value="－" class="btnspinner" data-cal="-1" data-target=".counter1" id="down" hovercolor="red">

</div>
```

```JavaScript
window.addEventListener('DOMContentLoaded', ()=>{
  const downbutton = document.querySelector('#down');
  const upbutton = document.querySelector('#up');
  const text = document.querySelector('#textbox');
  const counter = document.querySelector('#counter');
  downbutton.addEventListener('click', (event) => {
    counter.textContent=parseInt(counter.textContent)-parseInt(text.value);
  });
  upbutton.addEventListener('click', (event) => {
    counter.textContent=parseInt(counter.textContent)+parseInt(text.value);;
  });
});
```
CupertinoPickerでonSelectedItemChangedされた後に発動


CupertinoPickerで選択するたびに発動するイベント（onSelectedItemChanged）はありますが、連続で発動するので負荷がかかる処理はしたくないところです。
Timerで選び終わった後に１回だけ発動させます。

```dart
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:async';

//（略）

//Timerの設定
  Timer selectTimer;
  Timer _selectHandler() {
    if (selectTimer != null) {
      if (selectTimer.isActive) {
        selectTimer.cancel();
      }
    }

    return Timer(
      const Duration(seconds: 1),
      _select,
    );
  }

//最後に選択した1秒後に発動する
  void _select() {
    print(selectedArea);
  }
  
//CupertinoPickerが入っているWidget
  Widget _areaPicker(BuildContext context) {
    return GestureDetector(
      onTap: () {
        _showDemoPicker(
          context: context,
          child: BottomPicker(
            child: CupertinoPicker(
              backgroundColor:
                  CupertinoColors.systemBackground.resolveFrom(context),
              itemExtent: 30,
              children: areaList.map(_pickerItem).toList(),
              onSelectedItemChanged: (item) {
                setState(() => selectedArea = areaList[item]);
                selectTimer = _selectHandler();
              },
            ),
          ),
        );
      },
      child: Container(
          margin: EdgeInsets.fromLTRB(0, 0, 0, 20),
          padding: EdgeInsets.all(10.0),
          decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(5),
              border: Border.all(color: Colors.black12)),
          child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(selectedArea),
                Icon(Icons.swap_vertical_circle, color: Colors.black45)
              ])),
    );
  }
  
  //（略）
```
herokuで動くDjangoのmarkdownxの画像アップロード先をcloudinaryにした話

# あらすじ
副業案件でDjango製のブログサイトの開発をサポートしていたときのお話です。

ブログ記事はmarkdownで書きたいということで、[django-markdownx](https://pypi.org/project/django-markdownx/)を導入していました。
開発は難なく完了。
herokuにデプロイします。

なんと、__画像がアップロードできません__。

本来であれば、テキストエリアに画像をドロップすると、markdownxのjsによってアップロードされ、画像のパスがmarkdown形式でテキストエリアに表示されます。

本番環境で試してみると、画像をドロップ後、数秒たたないうちに画像のパスがテキストエリアに表示されましたが、プレビューに画像が表示されません。
コンソールを見ると、画像に対して404になっていました。
herokuにアクセスし、アプリケーションのディレクトリを確認すると、アップロード先に指定しているディレクトリに画像がありませんでした。

# 問題発覚
各所でも言及されていますが、herokuでは`DEBUG=False`のDjangoはファイルをアップロードできません。
`DEBUG=True`にして運用するわけにもいかないので先方と相談した結果、heroku+Djangoで割と実績のある[cloudinary](https://cloudinary.com/)を画像アップロード先とすることにしました。

cloudinaryのSDKをプロジェクトにインストールし、いざ。
しかし、今までと同様、テキストエリアに画像パスが表示されるものの、画像は表示されませんでした。

cloudinaryを直接確認してみると、アップロードしたファイルが存在していました。
ところが、ファイルのURLがテキストエリアに表示されたURLと異なるのです。

# 原因
原因は、markdownxとcloudinaryが__親切__だからでした。

markdownxさんは画像をアップロードするとき、既存のファイルとファイル名が衝突しないように、ファイル名をuuidに変更したうえでアップロードします。
![Untitled (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227222/270b0ef6-1820-133e-71bf-693bd494fb4a.png)


一方、cloudinaryさんもまた、既存のファイルとファイル名が衝突しないように、ファイル名をuuidに変更したうえで保存します。
![Untitled(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227222/0c2296b6-ab8a-8753-67d5-fbd4d8924d8c.png)

これらを組み合わせると、markdownxさんは名前を変えた上でcloudinaryさんに渡した後、cloudinaryさんがどんな名前にしてファイルを保存したのかを聞かず、自分が知っているファイル名をブラウザに返します。
この動きによって、cloudinaryにあるファイル名とテキストエリアに表示されるURLが異なっていました。
![Untitled(2) (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227222/8f8714d3-8ea3-6e5a-2374-3099ebe673bd.png)


# 解決策
markdownxさんには辞めてもらって、cloudinaryさんの独り言に耳を傾けましょう。

markdownxは、デフォルトでは画像アップロードをライブラリ内のビューで処理します。
設定を変更して、自前のビューに転送するよう変更します。

```diff:settings.py
+ MARKDOWNX_UPLOAD_URLS_PATH = '/upload'
```

画像アップロード処理用ビューを用意します。
markdownxの画像アップロードリクエストは、`'image'`という名前でファイルがきます。
レスポンスは`{"image_code": テキストエリアに表示する画像パス}`形式のJSONです。
cloudinaryのアップロードのレスポンスは辞書型で、`'url'`で画像URLを取得できます。

```diff:urls.py
+ path('upload', views.UploadView.as_view(),name='upload'),
```

```python:views.py
# 追記
import cloudinary
import cloudinary.uploader
import cloudinary.api
from django.conf import settings
from django.http.response import JsonResponse

class UploadView(View):
    def post(self,request, *args,**kwargs):
        file = request.FILES['image']

        cloudinary.config( 
            cloud_name = settings.CLOUDINARY_STORAGE['CLOUD_NAME'], 
            api_key = settings.CLOUDINARY_STORAGE['API_KEY'], 
            api_secret = settings.CLOUDINARY_STORAGE['API_SECRET']
        )
        res = cloudinary.uploader.upload(
            file = file,
            folder = settings.MARKDOWNX_MEDIA_PATH,
        )

        return JsonResponse({"image_code": f"![]({res['url']})"})
```

これで、markdownxを介さずにcloudinaryに直接アップロードし、正しいURLをテキストエリアで取得できるようになりました。

heroku + django + cloudinaryという組み合わせはメジャーそうなのに、markdownが絡んだ記事がなくて苦労しました。
誰かのお役に立てると幸いです。

みなさんも人の話には耳を傾けましょう。
[Microsoft] Azure AD B2C カスタムポリシー Identity Experience Framework なんもわからんリンク集

ただのリンク集です。

* [冴えないCustom Policyの育て方](https://blog.azure.moe/2019/11/22/%E5%86%B4%E3%81%88%E3%81%AA%E3%81%84custom-policy%E3%81%AE%E8%82%B2%E3%81%A6%E6%96%B9/)
    * ざっくりカスタムポリシーの概略です。
* [IEF開発者のWiki](https://github.com/azure-ad-b2c/azureadb2ccommunity.io/wiki)
    * 今はMSDNに移ったのでなんもないです。
    * レポジトリのほうにバックアップがあります。
    * MSDNよりわかりやすいかも。
* [Gaining Expertise with Azure AD B2C](https://aka.ms/LearnAADB2C)
    * Microsoftが出している教育用（？）ドキュメントです。
    * まだ読んでいませんが、これでなんとかなるかも？
* [Azure AD B2C を使用して外部ユーザーがアプリに安全にアクセスできるようにする](https://docs.microsoft.com/ja-jp/learn/modules/enable-external-access-with-b2c/)
    * Microsoft Learnのコンテンツです。
    * カスタムポリシーは出てこない（？）です。
Excelでオートシェイプを選択順にコネクタで接続する

#はじめに
フローチャートを綺麗につくるのは難しい。工程が増えると信じられない量のコネクタを繋ぐことに、、、
縦に長くなったフローチャートの各工程をメインの一本のみ（分岐とかは未対応）ひたすら繋ぐマクロの紹介です。
なぜかexcelで見つからなかったので、
以下参考URLです。
1. [エクセルで選択したオートシェイプを取得する](https://www.relief.jp/docs/excel-vba-get-name-selected-shapes.html)
2. [今回やりたいことのパワーポイント版](https://www.relief.jp/docs/powerpoint-macro-connect-selected-shapes.html)
3. [エクセルで図形を生成しコネクタを接続する](https://www.moug.net/tech/exvba/0120007.html)

##マクロ紹介
```vb
Sub connect()
    Dim con As Shape 'コネクタの定義
    Dim i As Long

    With Selection '以降ドット(.)で始まるものはSelectionを省略しますという構文
        For i = 1 To .ShapeRange.Count - 1　'選択数した図形の個数-1
            Set con = ActiveSheet.Shapes.AddConnector _(msoConnectorStraight, 1, 1, 1, 1) 'コネクタの種類の設定
            con.ConnectorFormat.BeginConnect .ShapeRange(i), 1 'コネクタ始点の指定
            con.ConnectorFormat.EndConnect .ShapeRange(i + 1), 1 'コネクタ終点の指定
            con.RerouteConnections　'一番近い箇所に接続しなおし
        Next i
    End With
End Sub
```

#最後に
ほぼ手抜きのため図形を選択していないと変なエラーになります。さらに、オブジェクトの選択カーソルでまとめて選択すると順番バグってちぐはぐに接続されます。
繋ぎたい順番にCtrl押しながら選択するのをおすすめします。
累積和の計算

https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_twopointers_step1

愚直にでも解けないことはないが計算量が増えるのは愚策、みたいな問題なので「そうそうこれこれそれっぽい」とnoob丸出しなことを言う。

まず愚直版

```java:Main.java
import java.util.Scanner;


public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        int n = sc.nextInt();
        
        int score = 0;
        for(int i=0; i<n; i++){
            score += sc.nextInt();
            System.out.println(score);
        }
    }
}
```

![キャプチャ_3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514170/2173026a-a718-e78a-0ddd-888747f1f169.png)
0.63秒……かかってるなあ。（チケットないので入力は見られてない）
というかお手本でもこの方法なので「これでいいんじゃね？」感はある。

（計算式だけを見て）累積和でやってみた。

```java:Main.java
import java.util.Scanner;


public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        int n = sc.nextInt();
        
        int[] a, b;
        a = new int[n];
        b = new int[n+1];
        
        b[0] = 0;
        
        for(int i=0; i<n; i++){
            a[i] = sc.nextInt();
        }
        
        for(int i=1; i<=n; i++){
            b[i] = b[i-1] + a[i-1];
        }
        
        for(int i=1; i<b.length; i++){
            System.out.println(b[i]);
        }
    }
}
```

![キャプチャ_3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514170/b18bd4ce-b095-8bfb-9acd-1a0ff861b4bc.png)

**変わってねえ**。
実装の仕方を間違えているのかもしれないが、ひとまず次の問題へ行こう。
ぶち当たってから考える。
JavaScriptにRailsの変数を持たせるには

今回オリジナルアプリの作成で、Railsの変数をJavaScriptで使えないかと調べて実装できたのでここに記録。

結論から言うとgemを入れたら簡単に実装できた。

まず、使用するのはgonと言うgem

Gemfileに`gem "gon"`と記載

ターミナルにbundle install

その後application.heml.erbのhead内に`<%= include_gon %>`と書くことでgonを読み取れるように

次に使用したいcontrollerの変数をJavaScriptで使えるように

```ruby 
@movie = Movie.find(params[:id])
gon.movie = @movie
```

変数`@movie`に`gon`を加える

あとはjsで変数を使えるように
今回はアラートを用いてアラートの内容に変数を用いたいため以下の記述

```javascript
alert(`正解は[${gon.movie.phrase}]です`);
```
AWSのEC2上に環境変数を設定する方法

# 環境
macOS: Big Sur Ver11.2.3
Rails: 6.1.1
Ruby: 2.6.5
インフラ：AWS(EC2)
Webサーバ：Unicorn

# 困っていること
AWSのEC2を使ってポートフォリオをデプロイし、さらにACMで証明書取得, Route53でドメイン取得後、SSL化まで行ったところ、Googleマップが表示されなくなった。
ブラウザのコンソールを確認すると「Google Maps JavaScript API error: InvalidKeyMapError」と表示されている。
したがって、APIキーをEC2上で設定できていないのではと推測。

# 解決方法
### ①EC2にSSHで接続し、Vimを開く
```terminal
% cd .ssh
% SSH接続のコマンド（ssh -i hoge.pem ec2-user@アプリのIPアドレス）

接続後、
[ec2-user@ip-172-31-0-160 ~]$ sudo vim /etc/environment
```

### ②環境変数を記述する
内容を変更するには「i」を押して編集モードにする。
変更し終わったら「esc」を押して編集モードを終了してから「:wq」で保存して終了すること。

```terminal
export GOOGLE_MAPS_API_KEY='APIキーを貼り付け'
```

### ③設定できたか確認
一度EC2から抜けます。

```terminal
[ec2-user@ip-172-31-0-160 ~]$ exit

ログアウトしたらもう一度EC２にログインし、以下のコマンドを実行
[ec2-user@ip-172-31-0-160 ~]$ env | grep 環境変数の名前
```

これで設定した環境変数が表示されればきちんと設定できています。

### ④Webサーバを一度ストップさせ、再起動させる
一度EC2を抜けて、ローカルのターミナル上でアプリケーションのフォルダに移動します。
以下のコマンドを実行し、Unicornをストップさせる。

```terminal
% bundle exec cap -t production unicorn:stop
```
次に、もう一度EC2にSSH接続してログインし、アプリのフォルダに移動します。
Unicornの起動状況を確認するとmasterプロセスなどが起動されていないと思います。

```terminal
[ec2-user@ip-172-31-0-160 take_out_app]$ ps aux | grep unicorn
ec2-user 16164  0.0  0.0 119436   916 pts/0    S+   03:05   0:00 grep --color=auto unicorn
```
ここまで確認できたら、Unicornを再起動しましょう！

```terminal
[ec2-user@ip-172-31-0-160 take_out_app]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
→特に何も表示はされませんが成功しています。
```
もう一度プロセスを確認！
masterとworkerという名前のプロセスが実行され、再起動できているのがわかります。

```terminal
[ec2-user@ip-172-31-0-160 take_out_app]$ ps aux | grep unicorn
ec2-user 16196  1.0 12.6 486816 127348 ?       Sl   03:08   0:01 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 16204  0.3 12.3 488336 123972 ?       Sl   03:08   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 16216  0.0  0.0 119436   948 pts/0    S+   03:10   0:00 grep --color=auto unicorn
```

これでブラウザでアプリケーションにアクセスしてみると、無事にGoogleマップが表示されていました！

# おまけ（Vimから抜けるコマンドまとめ）
① :w → 作成・編集したファイルを保存
② :q → vimをそのまま終了
③ :q! → 編集した内容を保存しないでvimを終了
④ :wq → 編集した内容を保存してvimを強制終了
ubuntu20.04環境でのpyenvとpipenv

# 目的
ubuntu20.04において、pyenvとpipenvを使ってpythonの仮想環境を構築する

# 環境
Ubuntu20.04

# 手順

## pyenvをinstallするshellscriptを準備

```bash:install-pyenv.sh
function setup-pyenv() {
  sudo apt update
  sudo apt install -y \
  build-essential \
  libffi-dev \
  libssl-dev \
  zlib1g-dev \
  liblzma-dev \
  libbz2-dev \
  libreadline-dev \
  libsqlite3-dev \
  git

  ls ~/.pyenv ||\
  git clone https://github.com/pyenv/pyenv.git ~/.pyenv

  grep '# pyenv init' ~/.bashrc ||\
  cat <<'EOF' >>~/.bashrc
# pyenv init
# ref: https://github.com/pyenv/pyenv
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init --path)"
EOF

}

# Main Function
function main() {
  setup-pyenv
}

main
```
## pyenvをinstallする

```shell-session:bash
$ ./install-pyenv.sh
```

# ワークフロー
```shell-session:bash
### pyenvで使いたいpythonのversionをinstallする
$ pyenv install --list
$ pyenv install 3.x.x

### directoryを作成する
$ mkdir myproject && cd pyproject

### pyenvで使いたいpythonのversionを指定し切り替える
$ pyenv local 3.x.x

### 切り替えたpythonのversionでpipを使ってpipenvをinstallする
$ pip install --upgrade pip setuptools
$ pip install pipenv

### pipenvの仮想環境に入る
$ pipenv shell

### pipenv環境から抜けるときはexit
$ exit

### 2回目以降は、そのdirectoryに行って、以下を実行する
$ pipenv shell
```


# Ref
ご教示ありがとうございます。

 - https://note.com/mokuichi/n/n627eb6773aad
 - https://qiita.com/KRiver1/items/c1788e616b77a9bad4dd
【小ネタ】プロキシ環境下でPythonのセットアップをした話をする

# はじめに

今回はプロキシ配下で Python を利用するときの注意点を書きます。

## Python の仮想環境を VSCode で実行する

settings.json の python.pythonPath を仮想環境上の python.exe にする。
以下のように指定する。
仮想環境内の.vscode フォルダにある settings.json に以下のように書く

```json
{
  "python.pythonPath": ".\\Scripts\\python.exe"
}
```

## pip の注意点

pip list は sitepackage のディレクトリが二つあると仮想環境上の package リストではなく
実際にインストールされている package を参照する。
仮想環境上の package リストを参照する場合は--path で参照する。freeze コマンドも然り

```bash
pip list --path .\Lib\site-packages
```

## プロキシを通して pip で numpy をダウンロード

```bash
pip install --proxy http://username:password@プロキシ URL:port numpy
```

## 信頼済みのホストとして登録するオプション

```bash
--trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org
```

## pip のアップグレード

```bash
python -m pip install --proxy http://username:password@プロキシ URL:port --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org --upgrade pip
```

## numpy のインストール

```bash
python -m pip install --proxy http://username:password@プロキシ URL:port --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org numpy
```

## pandas のインストール

```bash
python -m pip install --proxy http://username:password@プロキシ URL:port --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org pandas
```

```bash
pyhthon -m venv venv_test
cd venv_test\Scripts
activate.bat
python -m pip install -r requirements.txt --proxy http://username:password@プロキシ URL:port --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org
deactivate.bat
```

※requirements.txt にはインストールパッケージ名とバージョンを書きます。
【ゼロからのOS自作入門】フォロー1日目


とある事情で06/30までに「[ゼロからのOS自作入門](http://zero.osdev.jp/)」という本を読み終えたいと思うようになりました。
自律のため毎日勉強したことを投稿しようと思うのでよろしくお願いします。

<div align="center">
    <img src="http://zero.osdev.jp/book-cover.png" width="500px">
</div>

-----

# UEFI BIOSによる起動

- 電源を入れるとCPUはBIOSを実行する
- BIOSはパソコン本体や周辺機器を初期化する。
- BIOSはストレージから`.elf`ファイルを見つけ、それをメインメモリに読み出す
- BIOSは自分の実行を中断して、CPUはそのファイルを実行する

メインメモリの内容は電源を切ると消える。BIOS自体はROMにかかれている。

# OSを作る道具

- UEFI BIOSが実行するプログラムを**UEFIアプリケーション**という（アプリケーション…）
- これはバイナリファイルである
- バイナリファイルの作り方の例としてC/C++を使ったものがある
    1. ソースコード（`.cpp`, `.hpp`）を書く
    2. ソースコードを**コンパイル**して**オブジェクトファイル**（`.o`）を作る
    3. すべてのオブジェクトファイル（上ではソースコード1つにつきオブジェクトファイル1つが作られる）を**リンク**してまとめ、ひとつの実行可能ファイル（`.elf`）にする

簡単なプログラムの実行可能ファイル`a.out`は拡張子が違うだけで`.elf`ファイルと解釈して良いのかな？

# C言語でハローワールド

- 環境構築が済んでいれば`~/osbook/day01/c/hello.c`にソースコードがある
- プログラムの本体は最後にある`EfiMain()`だけ

```c
EFI_STATUS EfiMain(
        EFI_HANDLE       ImageHandle,
        EFI_SYSTEM_TABLE *SystemTable
    ) {
    SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello, world!\n");
    while (1);
    return 0;
}
```

これをClangとLLDを用いてコンパイルとリンクする

```bash
$ cd ~/osbook/day01/c/
$ clang -target x86_64-pc-win32-coff \ # ELFではなくWindows向けのCOFF形式で出力する
    -mno-red-zone -fno-stack-protector -fshort-wchar -Wall -c hello.c
$ lld-link /subsystem:efi_pplication /entry:EfiMain /out:hello.efi hello.o
```

- `clang`はLinux用コンパイラで`-target x86_64-pc-win32-coff`でWindows向けのCOFF形式で出力する（`lld-link`がCOFF形式を要求するため）
- `lld-link`はPE形式の実行可能ファイルを作るためのリンカだが、`/subsystem:efi_pplication`でUEFI用のPEファイルを生成してくれる
- できた`hello.elf`をUSBの`/EFI/BOOT/`に置いて起電すれば実行される
- この本ではQEMUで実行するために`$HOME/osbook/devenv/run_qemu.sh`というスクリプトを用意してくれている
- QEMUからマウスのカーソルを戻すには<kbd>Ctrl</kbd> + <kbd>Alt</kbd>を押す（焦った）

![Screenshot from 2021-06-03 10-32-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686583/be2c3034-a1bd-f7f1-5e43-c11bc691781e.png)


# PEとCOFFとELF

- アプリケーションは実行可能ファイルや設定ファイルから構成されている
- 実行可能ファイルにはいくつかのタイプがある
  - スクリプト（プログラミング言語によって書かれ、インタプリタというアプリが読み取って実行する。シェルスクリプトなど）
  - 機械語プログラムを中心とするもの（CPUが直接実行できる機械語をファイルの中に含んでいる）
- PE形式は機械語プログラムからなる実行可能ファイルの形式で、Windowsの標準
  - Windowsでは`.exe`, Linuxでは`.elf`
- COFF形式はオブジェクトファイル形式の一種。PE形式を作る過程で作られるやつ。
- ELF形式はオブジェクトファイル形式としても使える。PE形式は実行可能ファイル、COFF形式はオブジェクトファイル形式と別れているのに対し、ELF形式はどちらの形式も対応する。
- ELF = Executable and Linkable Format
- PE, COFF, ELFはx86-64 CPU用の機械語を格納するファイルという点で共通（文章を表すのにPDF, Word, HTMLの形式があるのと似ている）

-----

# 参考、役に立ちそうなリンク

- MikanOS ソースコード：https://github.com/uchan-nos/mikanos
- MikanOS 開発環境：https://github.com/uchan-nos/mikanos-build
- osdev-jp：https://osdev.jp/
- 著者（uchan）のTwitter：@uchan_nos
- [「ゼロからの OS 自作入門」サポートサイト](http://zero.osdev.jp/)
  - SlackやDiscordでサポート、勉強会（2021年3月27日から）を行っているらしい！　途中からかもだけど参加してみよっと。
- [ゼロからのOS自作入門をMacで勉強する方法 (Docker使用)](https://qiita.com/meruneru/items/0b7aa23ea505a80d60f5)
- [Docker ではじめる "ゼロからのOS自作入門"](https://zenn.dev/sarisia/articles/6b57ea835344b6)
- 追加していきます
DynamoDBの概要・メリット・デメリット（雑観）

vs RDS / Aurora Serverless
Webアプリケーションを作成する上での概要

# 特徴
- 完全マネージド
- Key Value Store
- Partation Key(必須) 

この値により、分散してデータが配置される。
「DynamoDB は、パーティション数にかかわらず、項目がテーブルのパーティション全体に渡って均一に分散している状態に対して最適化されています。」

- Sort Key
オプション、1テーブル一つまで。
使用する場合はPK + SKで一意になる必要がある。

検索速い 「ソートキー値順に物理的に近くに格納されます」

- GlobalSecoundaryIndex

インデックス
テーブル内の特定のカラムをPK / SKとした射影を生成する。
実態を持っているので、RDBで考えるとインデックスよりMaterialised Viewに近いかも。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html

# メリット
- オンデマンドならほぼ0円運用
- テスト環境とか超気軽に作りまくれる
- キャパシティをオートスケール出来る
- キャパシティあげてパラレルで処理をすることで、簡単に大量処理が出来る
- シンプルなKVSなので、設計が簡単（簡単とは言っていない）
- RDBのようなコネクション数の制限が無いので、lambdaベースのサーバレスアプリとの相性がいい

RDSは運用中はサイズ変えられない
AuroraServerelssはサイズ帰られる最低月額8000円くらい(postgresql互換なら160000円)
AuroraServerless V2で大幅に改善するらしい(期待)

# デメリット
主にRDB比較

- Indexが５個までしか設定できない
- group by / average / max / countとか使えない
- join出来ない => 非正規化必要
- not nullとかuniq indexみたいな制約が非常に弱い
- 1テーブルに全て乗せるのがパフォーマンス最強らしいけど、設計難しい
CakePHP4のデフォルトルーティングを無効にする

CakePHPの特徴の一つに、Controller名・action名・テンプレートファイル名を規約に沿った名前に統一することで、個別にルーティングを定義しなくても「/Controller名/action名」のURLに該当アクションを紐付けできる機能があります。（以下、デフォルトルーティングと書きます）
できるだけルーティングを書きたくない時には便利なのですが、画面表示が必要ないアクションでもルーティングが有効になってしまったり、URL構成からCakePHP製であることを推測されやすいため、無効化したい場合もあります。

CakePHP4のデフォルトルーティングは、routes.phpで使われている`DashedRoute`クラスの機能によるものです。
DashedRouteクラスではなく、Routeクラスを使用するように変更することで無効化できます。

```php:CakePHP初期状態のルーティング一覧
...cakephp>bin/cake routes
+---------------------+--------------------------+--------------------------------------------------------------------+
| Route name          | URI template             | Defaults                                                           |
+---------------------+--------------------------+--------------------------------------------------------------------+
| pages:display       | /pages/*                 | {"action":"display","controller":"Pages","plugin":null}            |
| pages:display       | /                        | {"action":"display","controller":"Pages","0":"home","plugin":null} |
| _controller:index   | /{controller}            | {"action":"index","plugin":null}                                   |
| _controller:_action | /{controller}/{action}/* | {"action":"index","plugin":null}                                   |
+---------------------+--------------------------+--------------------------------------------------------------------+
// 下2行がDashedRouteのデフォルトルーティング用定義
// DebugKit用のルーティングは除外しています。
```

routes.phpの定義内容から、以下の3行を削除します。

```diff_php:config/routes.php
<?php

- use Cake\Routing\Route\DashedRoute;
use Cake\Routing\RouteBuilder;

- $routes->setRouteClass(DashedRoute::class);

$routes->scope('/', function (RouteBuilder $builder) {
    $builder->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
    $builder->connect('/pages/*', 'Pages::display');

-   $builder->fallbacks();
});
```

```php:削除後のルーティング一覧
...cakephp>bin/cake routes
+---------------+--------------+--------------------------------------------------------------------+
| Route name    | URI template | Defaults                                                           |
+---------------+--------------+--------------------------------------------------------------------+
| pages:display | /pages/*     | {"action":"display","controller":"Pages","plugin":null}            |
| pages:display | /            | {"action":"display","controller":"Pages","0":"home","plugin":null} |
+---------------+--------------+--------------------------------------------------------------------+
// デフォルトルーティング用の定義が無くなります。
```

明示的にルーティングを定義しているURLへは、引き続きアクセスできます。
元々デフォルトルーティングで処理していたURLは、ルーティング定義が無いので404 Not Foundになります。
Anacondaで仮想環境を作成してJupyter Notebookのkernelに追加する方法 for Windows

#### 実行環境
- windows10 64bit(CPU: Intel Core i7, RAM: 16.0GB)
- Anaconda 4.10.1

##Anacondaで仮想環境を作成

###Anacond Promptから環境を作成
Anaconda Promptを起動
仮想環境名, パッケージ名を決めて仮想環境を作成

```
$ conda create -n ${仮想環境名} ${パッケージ名}
```

例: python3.7の環境 "test" を作成する場合

```
$ conda create -n test python=3.7
```

これで作成完了
仮想環境が作成されていることを確認

```
$ conda info -e
```

作成した仮想環境が表示されればOK

##Jupyter Notebookのkernelに反映させる
Anacondaに作成した仮想環境を起動

```
$ conda activate ${仮想環境名}
```

仮想環境にJupyterをインストール
```
$ conda install jupyter
```

Jupyterのkernelに仮想環境を追加

```
$ ipython kernel install --user --name=${仮想環境名}
```

これで追加完了

## おまけ
###Anacond Promptから環境を作成
結局Anaconda Promptを使うことになるけどAnaconda Navigatorから仮想環境の作成だけなら可能
Anaconda Navigatorを起動
Environments → Createを選択
ポップアップ（Create New environment）

- Name: 作成する仮想環境名
- Package: PythonかRにチェック（Pythonはセレクトボックスからバージョンを選択）
→ Create
![AnacondaNavigator_CreateNewEnvironment.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305927/87485aa3-353e-9a12-2629-bc8d79b21111.jpeg)
これで作成完了

## 参考
[【たったの３行！】仮想環境をAnacondaで作りJupyterカーネルとして利用する方法！
](https://wakaba-mafin.hatenablog.com/entry/anaconda-environment-on-jupyter)
ASP.NET上で「WebBackgrounder」を使って、バックグラウンドタスクを実装しました。

<h2>はじめに</h2>

ASP.NET上で「WebBackgrounder」を使って、バックグラウンドタスクを実装しました。

現在、ASP.NETでＷｅｂシステムを構築中で、利用者の登録時にバックグラウンド処理が必要になったので、何かないか探していたところ、「WebBackgrounder」というパッケージがあったので、使ってみました。

この「WebBackgrounder」というパッケージは、MicrosoftのWeb開発のベストプラクティス－ASP.NET では行わないことと、その代わりに行うことの記事で紹介されていたので、使えるかなあと
 ↓
https://docs.microsoft.com/ja-jp/aspnet/aspnet/overview/web-development-best-practices/what-not-to-do-in-aspnet-and-what-to-do-instead


やりたいことは、以下の利用者登録処理で、本登録の有効時間（７２時間）を設定し、バックグラウンドタスクで、有効時間が過ぎた仮登録の情報を削除する処理です。

利用者がＷｅｂシステムを使うため、利用者登録を行い、仮登録を行う。
　↓
利用者に本登録用のメールを送る
　↓
利用者がメールからのＵＲＬにアクセスして本登録を行う。

<h2>WebBackgrounderの入手</h2>
WebBackgrounderをnugetから入手。バージョン0.2.0が最新ですが、2012年から更新されていません。枯れた技術です。
 ↓
https://www.nuget.org/packages/WebBackgrounder

<h2>参考ソース</h2>
まず初めに、Webアプリ開始と終了時に、WebBackgrounderの開始と終了処理を記述します。

```Global.asax.cs(抜粋)
public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        GlobalConfiguration.Configure(WebBackgrounderSetup.Start);
    }

    protected void Application_End(object sender, EventArgs e)
    {
        GlobalConfiguration.Configure(WebBackgrounderSetup.Shutdown);
    }
}
```

次に、WebBackgrounderSetupでは、任意のジョブクラスを登録します。ジョブクラスでは、
任意の周期でタスクが実行できます。今回は１分周期でジョブが実行されます。

今回はジョブが１つだけですが、任意の周期でジョブが登録できます。


```WebBackgrounderSetup.cs(抜粋)
public static class WebBackgrounderSetup
{
    private static readonly JobManager jobManager = CreateJobWorkersManager();

    public static void Start(HttpConfiguration config)
    {
        jobManager.Start();
    }
    public static void Shutdown(HttpConfiguration config)
    {
        jobManager.Dispose();
    }

    private static JobManager CreateJobWorkersManager()
    {
        var jobs = new IJob[]
        {
            new UserStatusUpdateJob("UserStatusUpdateJob", TimeSpan.FromMinutes(1)),
        };

        var coordinator = new SingleServerJobCoordinator();
        var manager = new JobManager(jobs, coordinator);
        return manager;
    }
}
```
最後に、ジョブクラスでは、WebBackgrounder.Jobクラスを継承したクラスを実装します。


```WebBackgrounderSetup.cs(抜粋)
public class UserStatusUpdateJob : Job
{
    public UserStatusUpdateJob(string name, TimeSpan interval) : base(name, interval)
    {
    }

    public override System.Threading.Tasks.Task Execute()
    {
        return new Task(() =>
        {
            UpdateStats();
        });
    }

    public void UpdateStats()
    {
         // 有効時間が過ぎた仮登録の情報を削除処理

    }
}
```
Rustのstd::convertのFromとかIntoトレイトがわからなくなった時に見る記事

# この記事のモチベーション

Rustの`std::convert`には`From`や`Into`、`As`などがありますが、トレイトがネストしてるときに何から何への変換なのかがわからなくなったので備忘録的にまとめてみました。

https://doc.rust-lang.org/std/convert/index.html

# 結論

`From`と`Into`はムーブする破壊的な変換、`As`はムーブしない非破壊的な変換

# 実体の変換系

`From<T>`と`Into<T>`は逆の関係を持つ。

# Fromトレイト

`A`が`From<B>`を実装していると、`B`から`A`へ向かって変換できる。例えば、`String`は`From<&str>`を実装しているので、`&str`から`String`へ変換できる。ムーブが発生する。

https://doc.rust-lang.org/std/convert/trait.From.html

# Intoトレイト

`A`が`Into<B>`を実装していると、`A`から`B`へ向かって変換できる。例えば、`String`は`Into<&str>`を実装しているので、`String`から`&str`へ変換できる。ムーブが発生する。

https://doc.rust-lang.org/std/convert/trait.Into.html

# 参照の変換系

## AsRefトレイト

`A`が`AsRef<B>`を実装していると、`A`を`&B`に変換できる。例えば、`String`は`AsRef<str>`を実装しているので、`String`から`&str`へ変換できる。

https://doc.rust-lang.org/std/convert/trait.AsRef.html

## AsMutトレイト

`A`が`AsMut<B>`を実装していると、`A`を`&mut B`に変換できる。例えば、`String`は`AsMut<str>`を実装しているので、`String`から`&str`へ変換できる。

https://doc.rust-lang.org/std/convert/trait.AsMut.html


ここで注意したいのは
- `String`
- `&String`
- `&&String`

のどれでも`String`に対して`as_mut()`または`as_ref()`したのと同じになる。つまり、

```rust
fn main() {
    let x:String = "hoge".to_string();
    let _:&str = x.as_ref();
    let _:&str = &x.as_ref();
    let _:&str = &&x.as_ref();
}
```

である。
テックキャンプを受講した感想

##結論
ITスクールをテックキャンプにして良かったと思います。理由は、確実にITエンジニアとして転職ができること、学習と転職の時にしっかりサポートしていただけること、親切な対応をしてくれるからです。

#受講前のカウンセリング
受講してもらうためにポジティブな回答が多いです。私は「コロナ禍でもITエンジニアとして転職できますか？」「ITエンジニアとして長く勤められますか？」という質問をしましたが「全然問題なく働けますよ！」という回答でした。しかし、転職の際、キャリアアドバイザーの方から「絶対に転職できるとは言い切れないです。」という回答でした。

##カリキュラム
随所にヒントのあるカリキュラムなので進められなくはないと感じました。プログラミングが楽しいと思える難易度だと思います。railsのアプリ開発をしながらプログラミングを学習しますが、コピペしながらアプリの形式や文法を理解していきます。分からない部分はメンターさんに質問します。ただ、カリキュラムが進行するにつれて質問する内容が制限されるので履修難易度が上がります。

##受講形式
コロナ禍なのでリモートで受講しました。交通費もかからず、静かな環境で学習できたのでリモートで良かったと思いました。

##チーム
チーム分けされた同期で朝礼やアウトプット、ミーティングを行います。1時間ごとのアウトプットは有意義だと思いました。理由は、自分が学習している内容をアウトプットに向けてまとめることができたからです。

##Rubyテスト
こちらのテストはカリキュラムの終盤にありますが、難しかったです。元ITエンジニアのライフコーチの方も難しいとおっしゃってたので、このテストができなくても落ち込む必要はないと思います。

##オリジナルアプリ開発
自分でテーマを考えてアプリを開発します。私は、kindleで参考書を２冊購入して開発をしました。理由は、自分が思いついたアプリをインターネットのコードで開発してみましたが、エラーが発生してそのエラーを修正できなかったからです。

## 転職活動
活動期間66日、総応募数241社、面接19社、内定3社です。３0代前半、転職回数多めの経歴です。コロナ禍でしたが、SES企業に転職することができました。私は、テックキャンプで転職活動が一番辛かったです。圧迫面接や、内定をもらって出社してから希望しているWEB開発の仕事は無いと言われたり、大卒で大手企業経験の方でもひどい面接されるみたいです。なので、ITエンジニアを目指すなら若いうちに受講した方が良いです。若い方は内定が早くもらえるみたいです。

##就職軸
就職軸に最初からプログラミングができる企業に設定しました。

#転職サポート
キャリアアドバイザーの方がフォローしてくださります。圧迫面接があったり、対応が酷い企業が多数あるので精神的に疲弊します。その時は、週一で相談して心を癒しましょう。

##SES企業
設立から10年目のSES企業に内定致しました。キャリアの長いSES企業さんだとコネクションがあり、希望する職種が通りやすいそうです。

##転職後の学習
Udemyとpaizaとcodeprepで学習しています。言語はJAVAとJavaScriptとPHPに絞って学習しています。この3言語の理由は、フリーランスエンジニアシェアで約60％を占めています。つまり、この３言語を習得していると会社を退職した時に、フリーランスエンジニアとして仕事をいただける確率が上がると思ったからです。
【heroku】デプロイ後の更新を反映させる

herokuにて既にデプロイしているアプリを更新した際に、更新を反映させる手順を残しておきます。

### 1. 変更したファイルをステージングに追加する
```
git add .　　//変更があったすべてのファイルをステージングに追加
git add ファイル名　　//指定したファイルをステージングに追加
```

### 2. ステージングに追加した変更をコミットする
```
git commit -m "コメント"
```

### 3. コミットした変更をherokuにpushする
```
git push heroku master
```

### 4. migrationファイルにも変更があれば
```
heroku run php artisan migrate:rollback
heroku run php artisan migrate
```
<br>

【参考サイト】
https://entsukablog.com/laravel-heroku-deploy/#i
wp.apiFetchでFormDataを送信する

TL;DR
-

``data``ではなく``body``にFormDataオブジェクトをセットします

```php
wp.apiFetch({
  path:'/path/to/api',
  method: 'POST',
  body:FormDataObject
});
```

詳細
-

[wp.apiFetch](https://github.com/WordPress/gutenberg/blob/trunk/packages/api-fetch/src/index.js)では``data``で渡された値は``JSON.stringify()``を通してから
``body``にセットするようになっています


[公式のドキュメント](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-api-fetch/)にある通り``wp.apiFetch``では[fetch](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch)の全てのオプションがそのまま使えるので
``wp.apiFetch``で``FormData ``を送信したい場合は``data``ではなく``body``としてセットして
``JSON.stringify()``を通されないようにします
MLサーバソフトのReply-Toの扱い

#はじめに

メーリングリスト(ML)サーバの更新を計画しています。

CentOS7+fml-4.0-stable-20040215の環境を CentOS8 Stream + Mailman-2.1.29に更新を計画しました。

Reply-Toの扱いについて調べました。

#FML4
FML4では標準ではMLアドレスがReply-Toに設定されます。

標準で付けないようにするにはconfig.phの最後に以下を加筆します。

```/var/spool/fml/ML-NAME/config.ph
&DEFINE_FIELD_ORIGINAL('reply-to');
```

Ref: https://www.fml.org/software/fml4/Japanese/header_rewrite/1.html

#Mailman

mailmanは標準ではReply-Toは設定されません。標準でMLアドレスをつけるようにするにはWebの設定メニューで以下の修正をしてください。

```
投稿された記事の返信先を選んでください。 ほとんどのメーリングリスト
では 投稿者 を選ぶことを 強く 推奨します。(reply_goes_to_listの詳細)

上記選択で「投稿者」から「このリスト」に修正してください。
```

#調査
投函者がメールにReply-Toを追加した場合と非追加の場合の挙動は以下のとおりです。

横軸の「標準追加」とはMLサーバソフトの設定で追加する設定にした場合で、「標準非追加」とはMLサーバソフトの設定で追加しない設定にした場合です。

##FML4
|             | 標準追加  |標準非追加    |
| ------------|----------- | ------------- |
| 投函者追加   | 投函者設定値 | 投函者設定値 |
| 投函者非追加 |  MLアドレス | 無し          |

##Mailman
|             | 標準追加  | 標準非追加   |
| ------------|----------- | ------------- |
| 投函者追加   | 両方保持され2個設定 | 投函者設定値   |
| 投函者非追加 | MLアドレス  | 無し           |


となりました。ここで驚いたのはMailmanの挙動で、MLサーバソフトの設定で追加して、かつ投函者が追加するとReply-Toが2個設定されます。投函者が追加したのを優先してMLアドレスは非追加にして欲しい気がしますが、そのような挙動になる設定方法は見つけられませんでした。
JenkinsをMacにインストールした時のメモ


**実行環境**
■ macOS Catalina
■ バージョン 10.15.5

# 1. インストール

↓ 参考サイト
https://qiita.com/shirasaya0201/items/863a05117c934856e532

↓ 公式サイトにある通りhomebrewでインストール
https://www.jenkins.io/download/lts/macos/

```
$ brew install jenkins-lts
```

↓ エラーが出力されてしまう

```
Error: /usr/local/Cellar is not writable. You should change the
ownership and permissions of /usr/local/Cellar back to your
user account:
  sudo chown -R $(whoami) /usr/local/Cellar
Traceback (most recent call last):
	7: from /usr/local/Homebrew/Library/Homebrew/brew.rb:13:in `<main>'
	6: from /usr/local/Homebrew/Library/Homebrew/brew.rb:13:in `require_relative'
	5: from /usr/local/Homebrew/Library/Homebrew/global.rb:29:in `<top (required)>'
	4: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
	3: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
	2: from /usr/local/Homebrew/Library/Homebrew/system_command.rb:3:in `<top (required)>'
	1: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- plist (LoadError)
```

権限を書き換える必要があるみたいなので、
エラーに記載されている通りに下記コマンド実行して権限を変更

```
$ sudo chown -R 'whoami' /usr/local
```

再度インストールのコマンドを実行してみる

```
$ brew install jenkins-lts
```

↓ インストールは進むが最後のほうでまたエラーが出力されてしまった

```
Error: Failed to link all completions, docs and manpages:
  Permission denied @ dir_s_mkdir - /usr/local/share/fish
Error: The following directories are not writable by your user:
/usr/local/etc
/usr/local/include
/usr/local/lib
/usr/local/share

You should change the ownership of these directories to your user.
  sudo chown -R $(whoami) /usr/local/etc /usr/local/include /usr/local/lib /usr/local/share

And make sure that your user has write permission.
  chmod u+w /usr/local/etc /usr/local/include /usr/local/lib /usr/local/share
```

また権限周りでエラーが出ているようなの、
エラーに記載されている通りに下記コマンド実行して権限を変更

```
$ sudo chown -R $(whoami) /usr/local/etc /usr/local/include /usr/local/lib /usr/local/share
$ chmod u+w /usr/local/etc /usr/local/include /usr/local/lib /usr/local/share
```

再度インストールのコマンドを実行してみる

```
$ brew install jenkins-lts
```

↓ 今度は成功したようです

```
🍺  /usr/local/Cellar/jenkins-lts/2.222.4: 7 files, 66.2MB, built in 4 seconds
```

# 2. Jenkins起動

公式サイトにある通り、下記コマンドを実行

```
$ brew services start jenkins-lts
```

http://localhost:8080
にアクセスしてJenkinsのログイン画面が表示されていれOK
<img width="957" alt="スクリーンショット 2020-06-18 9.04.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88968/ecf86790-65ee-c179-4e60-4be816004b6a.png">

# 3. 他PCからアクセスできるようにする

デフォルトだと他のPCからはアクセスできないようなので、下記ファイルの設定を編集して保存。

```
$ sudo vi /usr/local/opt/jenkins/homebrew.mxcl.jenkins.plist

[編集前]
<string>--httpListenAddress=127.0.0.1</string>

[編集後]
<string>--httpListenAddress=0.0.0.0</string>
```
編集したらJenkinsを再起動

```
$ brew services restart jenkins
```

# その他

Jenkinsを停止する時

```
$ brew services stop jenkins-lts
```
Salesforceデータ更新ヒント集


#Salesforceの日付型に対しデータを更新する場合の注意点
Xplentyでは、Date型という型はないため、文字列型もしくはDateTime型で処理されます。

Xplentyで変換を行う場合、以下になります。

例えばCSVファイルをSalesforceへ連携する場合の日付型の扱いについて紹介します。

|商談ID | クローズ予定日 | 商談名|
|:-----------|------------:|:------------:|
|0062x000005elWKAAY	|2021/5/11| テスト|


クローズ予定日は「2021/5/11」となっており、yyyy/M/d形式となっています。
これをSalesforceに入れる場合、Xplentyでは**String**型もしくは**DateTime**型のまま、Salesforceコンポーネントに連携することにより、クローズ予定日を追加もしくは更新することが可能です。

##文字列型で連携する方法
Salesforce側のDate型のフィールドにyyyy/M/d形式のまま、データを入れることはできないので、以下のyyyy-M-d形式（もしくはyyyy-MM-dd形式）に変換する必要があります。
2021/5/11 > **2021-5-11**
変換式：`REPLACE(*クローズ予定日のfield名*,'/','-')`
結果：**2021-5-11**

**もし上記のFiledの値がNULLの場合、NULLが返されます。**


##DateTime型での連携
Salesforce側のDate型のフィールドにDateTime型に変換し、挿入することも可能です。その場合、
変換式：`ToDateCustomFormats(*クローズ予定日のfield名*,'yyyy/M/d') `
結果：**2021-05-12T00:00:00.000Z**
**もし上記のFiledの値がNULLの場合、NULLが返されます。**

Xplenty側ではDateTime型のデータをSalesforceに投入時に日付型「2021-05-12」に自動的に変換されるので、問題ありません。

##SalesforceのオブジェクトのIDフィールド（(AccountIdやOwnerId)）に使われるHexstring（16進文字列）型のフィールドを文字列型に変換するには？
Xplentyでは「0052x0000034oJqAAI」のような値を文字列として変数画面で使用した場合、Hexstring（16進文字列）として自動的に扱われます。こうした場合、Chararray関数を使用して文字列型へ変換しようとするとエラーとなってしまいます。
そこでHexstring（16進文字列）の値を文字列型で定義し、パイプラインの条件やSelectコンポーネントで使用したい場合、バックスラッシュを使い「\'[Hexstring文字列]\'」のように定義することで、文字列に変換が可能です。

例）**文字列「0052x0000034oJqAAI」を変数で文字列型として定義する場合**
`'\'0052x0000034oJqAAI\''`
M1 MacでAndroidエミュレータを使用する方法（メモ）

初心者エンジニアです。

M1 macを使用していて、AndroidStudioのエミュレータが起動出来ない方向けです。
自分がこの設定に時間がかかったので、メモベースでまとめておきます。

# 結論
・プレビュー版を使用する
・Android Studioでエミュレータを起動させる

##### どちらも設定をしないと現段階（2021/06/03時点）では動作しません。

# プレビュー版を使用する

M1 Macbookではエミュレータが使えないということで、2020年の12月頃にGoogleがAndroidのデモ操作をできるパッケージを提供しました。

そのパッケージを使うことでAndroid Emulatorというアプリをダウンロードして起動してデモ操作ができるようになりました。しかし、機能は限定されているみたいです。

[プレビュー版github経由](https://github.com/google/android-emulator-m1-preview)

導入方法で参考にさせていただいたサイトです。
以下の手順を見ながら設定を行なっていくと使用できました。

[プレビュー版設定手順](https://minpro.net/android-emulator-for-m1-mac)

設定の途中でpathを通すというのがわからなかったので、参考にさせていただいたQiitaも貼っておきます。
[【zsh, bash】macでPATHを通す方法 - not found と出てしまったら
android エミュレーター](https://qiita.com/k3ntar0/items/eb8cdbd8eba9da388def)

# Android Studioでエミュレータを起動させる

私はプレビュー版で設定できたので、こちらはやっていませんが、

<<参考>>
[M1 MacでAndroid エミュレータを開く方法 <パッケージ使わない> (Android Studio, Flutter)](https://qiita.com/Naga_Ayuu/items/2f029b365d5d4c43402b)

https://github.com/google/android-emulator-m1-preview/issues/34
fvm インストール

公式Document
https://fvm.app/docs/getting_started/installation
に従って

```
brew tap leoafarias/fvm
brew install fvm
```
を実行したがエラー


```
Error: Can't create update lock in /usr/local/var/homebrew/locks!
Fix permissions by running:
  sudo chown -R $(whoami) /usr/local/var/homebrew
==> Tapping leoafarias/fvm
fatal: could not create leading directories of '/usr/local/Homebrew/Library/Taps/leoafarias/homebrew-fvm': Permission denied
Error: Failure while executing; `git clone https://github.com/leoafarias/homebrew-fvm /usr/local/Homebrew/Library/Taps/leoafarias/homebrew-fvm --origin=origin` exited with 128.
```

このエラーはこの対応を行った
```
sudo chown -R $(whoami) $(brew --prefix)/*
```

次にCommand Line Tools のバージョンに関するエラーメッセージ

```
Error: Your Command Line Tools are too outdated.
Update them from Software Update in System Preferences or run:
  softwareupdate --all --install --force

If that doesn't show you any updates, run:
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

Alternatively, manually download them from:
  https://developer.apple.com/download/more/.
You should download the Command Line Tools for Xcode 12.5.

Error: Your Command Line Tools (CLT) does not support macOS 11.
It is either outdated or was modified.
Please update your Command Line Tools (CLT) or delete it if no updates are available.
Update them from Software Update in System Preferences or run:
  softwareupdate --all --install --force

If that doesn't show you any updates, run:
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

Alternatively, manually download them from:
  https://developer.apple.com/download/more/.
You should download the Command Line Tools for Xcode 12.5.
```

素直にCommand Line Tools for Xcode 12.5. を入れて再実行（Xcode12.5も）

```
brew install fvm
```
fvmのインストールが成功したらfvmからflutterをインストール

利用可能なバージョン

```
fvm releases
```

1.22.6 と 2.2.1 をインストール

```
fvm install 1.22.6
fvm install 2.2.1
```

インストールされていることを確認

```
fvm list
```

指定のバージョンをグローバルのデフォルトに設定

```
fvm use 1.22.6 global
```
（fvmの1系では --global だったような気がするので変わった？）

PATHにデフォルトのflutterを追加するときは以下を追加

```
$HOME/fvm/default/bin
```
応用数学

１．線形代数
<要点のまとめ>
スカラー、ベクトル、行列について学ぶ。
行列は連立方程式から生まれた。
逆行列は、行列に掛け合わせると単位行列になるもの。
行列式・・・逆行列が存在するか判定できる。行列式=0は逆行列が存在しない。
固有値・・・$Av=lv$となるlを固有値、vを固有ベクトル
特異値分解・・・$Mv=ρu$、$M^Tu=lv$ なる$u$, $v$が存在するとき、$M=US^{-1}V$と分解できる。
⇒特異値は初めてであったため、苦労した。
２．確率
条件付き確率
$$ P(Y|X)=\frac{P(Y,X)}{P(X)} $$
XとYが独立な場合の確率は、下記が成り立つこと
$$ P(X,Y)=P(X)P(Y) $$
ベイズ則は下記の公式。
$$ P(X|Y)=\frac{P(Y|X)P(X)}{P(Y)} $$
確率変数は、事象に対する数値の写像
$$ f:X->R $$
期待値は、下記の定義(Xが離散の場合)。
$$ E(f) := \sum_{x \in X}{f(x)P(x)} $$
Xが連続の場合は、一般に下記で定義される。
$$ E(f) := \int_{X}{f(x)P(x)dx} $$
分散は、下記のように定義される。
$$ Var(f) = E((f - E_f)^2) $$
分散公式として書きが成り立つ
$$ Var(f) = E(f^2) - E(f)^2 $$
共分散は下記で定義される。
$$ Cov(f, g) := E((f - E_f)(g - E_g)) $$
３．情報理論
自己情報量
$$ I(x) := -log(P(x)) $$
シャロンエントロピー
$$ H(x) = E(I(x)) $$
カルバックライブラーダイバージェンス 確率分布の違いを表す
$$ D_{KL}(P||Q) := \sum{P(i)\log{\frac{P(i)}{Q(i)}}}$$
カルバックライブラーダイバージェンスはWikipedia見た方がわかりやすい。
https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%83%BB%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%BC%E6%83%85%E5%A0%B1%E9%87%8F#:~:text=%E3%82%AB%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%83%BB%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%BC%E6%83%85%E5%A0%B1%E9%87%8F%EF%BC%88%E3%82%AB%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%83%BB%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%BC%E3%81%98%E3%82%87%E3%81%86,%E3%82%92%E8%A8%88%E3%82%8B%E5%B0%BA%E5%BA%A6%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82
交差エントロピー
$$ H(p, q)= H(p) + D_{KL}(P||Q)$$

考察：交差エントロピーは、$p$の事象を$q$の確率分布に基づく符号化方式であらわした場合に必要なビット数を表す。
$p$の事象は、本来、$H(p)$のビット数で表現できる。ところが、$p$の事象を$q$の事象に基づく符号化方式で用いた場合、当然$H(p)$よりは必要なビット数が増える。その増加分が$D_{KL}(P||Q)$である。

演習問題や参考図書、修了課題のレポート>
Rで演習問題を解けるので、Rを使うのはおすすめ。
問2.1.1𝐴𝑣
A = rbind(c(1, 3, 4), c(5, 9, 0), c(3, 1, 2))
v = rbind(c(1), c(0), c(3))
A %*% v
結果
     [,1]
[1,]   13
[2,]    5
[3,]    9
railsチュートリアル　５章　備忘録


備忘録の用途
---
１脳のインデックスの外部保存化
２自分ってすごいなと思うため。self esteemが高い人ほど失敗を前向きに捉えるため人生うまくいくらしい。
(引用文献: "DOES HIGH SELF-ESTEEM CAUSE BETTERPERFORMANCE, INTERPERSONAL SUCCESS, HAPPINESS, OR HEALTHIER LIFESTYLES?"
https://www.researchgate.net/publication/296629428_Does_high_self-esteem_cause_better_performance_interpersonal_success_happiness_or_healthier_lifestyles)

まとめ
---
・プリプロセッサ,コンパイルとカタカナが頻出した。

・Bootstrapは少ないコードで簡易的なサイトの色つけを行ってくれる。

・新規ページを作成する時の流れは、
add test code(test)->add routes (routes.rb)->add action(controller)->add view(view)
となっている。MVCの流れ通りに作成されるんですね。

<h3>プリプロセッサ

プリプロセッサとは、プログラミング言語処理系においては、ソースコードに対して、それらがインタプリタやコンパイラなどの本体に渡される前に、前処理を施すプログラムがプリプロセッサと呼ばれている

（引用文献:Wikipedia https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AA%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5）
難しい、、
プログラマーが書いたコードをパソコンが認識しやすいように変換してくれる機能かな？
主にプリプロセッサでは以下４点を行っているらしい。
・ファイルの読み込み (including)
・マクロの展開（シンボルを、あらかじめ定義された規則に従って置換する）
・コンパイル条件によるソースコードの部分的選択
・コメントの削除
<h3>コンパイル
コンパイルとは、プログラミング言語で記述されたソフトウェアの設計図（ソースコード）を、コンピュータが実行可能な形式（オブジェクトコード）に変換する作業のことです。

（引用文献:Wikipedia https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9）
ソースコード⇨プリプロセッサ⇨コンパイル⇨コンピュータ
の順でコードがPCに入力されていくんだろうなと思ってる。

次章からサイトの肉付けが始まっていくらしい。楽しみ。Happy Coding!

参考文献
---
"DOES HIGH SELF-ESTEEM CAUSE BETTERPERFORMANCE, INTERPERSONAL SUCCESS, HAPPINESS, OR HEALTHIER LIFESTYLES?"
https://www.researchgate.net/publication/296629428_Does_high_self-esteem_cause_better_performance_interpersonal_success_happiness_or_healthier_lifestyles

Wikipedia コンパイラとは　
https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9

Wikipedia プリプロセッサとは
https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AA%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5
GitLabのストレージ消費が気になったので調べてみた

# とある日のこと
GitLabで普段使用しているプロジェクトのトップページを見ていたら、ストレージ消費が多いことに気がつきました。

![gitlabstorage.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67228/3ed757e2-f1c2-5a4c-4d5b-0b969db7ea22.jpeg)

レポジトリが162MB（まあこれも小さくはないですが）に対して10.8GB と**66倍**もストレージを消費しています。
このプロジェクトは作成して半年程度の若いプロジェクトであり、このまま肥大化を続けると、GitLabのサーバ管理者に迷惑をかけてしまうので、何に消費されているかを調査することにしました。

# ストレージの内訳
レポジトリのサイズはgitレポジトリ単体のサイズですが、Storageのサイズはそのプロジェクト全体で消費されるデータ容量のことで、例えば以下のものが含まれます。

- Wikiのテキストおよび添付ファイル
- Git LFS
- Job Artifacts

このうちのどれが容量を消費しているのかはGitLabのAdmin権限があれば画面上で確認できます。

が、**実はAdmin権限がなくても以下のAPIから確認できます。**

```
/api/v4/projects/:PROJECT_ID?statistics=true
```

```yaml
statistics:
  commit_count: MASKED
  job_artifacts_size: 11476176499
  lfs_objects_size: 0
  packages_size: 0
  repository_size: 170194370
  snippets_size: 0
  storage_size: 11647996161
  wiki_size: 1625292
```

`job_artifacts_size`がStorage消費のほぼすべてを占めていました。

# Job Artifactsの内訳
Job ArtifactsはGitLab CIのジョブが消費するストレージです。

このプロジェクトでは`gitlab-ci.yml`で毎日スケジュールジョブを回していましたが、そのジョブの`artifacts`セクションは特に指定しておらず、不思議でした。

よく調べたところ、ジョブのコンソールログがストレージ消費の犯人ではないかという仮説が立ちました。
ジョブのログを確認すると、非常に大きいサイズのログが出ていることがわかりました。
1ジョブあたりのログサイズとこれまでに実行されたジョブの回数から見積もりを計算すると、ストレージ消費量と概ね一致することが確認できました。

# 対策
残念ながらGitLabには古いジョブのログを自動的に削除する機能はないようです。代替案として以下のようにしました。

- ジョブを実行する場合にコンソールに出すログがでかくなりすぎないように`tail`コマンドでtrimする。
- 一方、デバッグ用にフルログが一定期間残っていて欲しいので、`tee`コマンドでファイルに書き出して`artifacts`セクションで明示的に指定し、有効期限を設定する。

```yaml
build:
  script:
    - create_large__cmd | tee -a console_full.log | tail -n 1000
  artifacts:
    paths:
      - console_full.log
    expire_in: 1 week
```
      
# まとめ
- GitLabのストレージ消費の内訳は `/api/v4/projects/:PROJECT_ID?statistics=true` で確認できます
- ジョブのコンソールログは自動削除できないので、長いログはファイルに書き出して明示的に`artifacts`に指定しましょう。
AI-900 勉強法

#はじめに
現在自分は専門学校生で、学校で「資格試験やるから勉強しといてね」と言われ勉強することに…

受験料は？
[公式ページ](https://www.google.com/url?sa=t&source=web&rct=j&url=https://mta.odyssey-com.co.jp/outline/AI-900.html&ved=2ahUKEwiKkrG4tPDwAhUWPXAKHSXFB0sQFjABegQIBBAF&usg=AOvVaw3xIPYP7P8L50dqDs7ZN9WV)
＜社会人/一般の方＞ 1科目 13,200円（税込） 
＜学生の方（学割）＞ 1科目 7,700円（税込）

高い！
さすが天下のMicrosoft様！
さすがにこれをもう一度受験料払って受けたくはない
よし、勉強するか
ちなみに、今回の勉強期間は1ヶ月弱でした
(総勉強時間は3日弱くらい)

#やり方
[公式ドキュメント](https://docs.microsoft.com/ja-jp/learn/certifications/exams/ai-900?tab=tab-learning-paths)を読んで暗記して実際に触って覚える

正直過去問が存在してなかった時点でこれしか方法がない、がこれで割と点数が取れる

自分は暗記が苦手だが762/1000までは取れたので普通に勉強ができる人ならもっと取れると思う

知識チェックは定期的にやり、全問正解できるようにはしておいた方がいい
ただし、**知識チェック外からも問題が出る**ので慢心しないように

知識チェック外からの問題は公式ドキュメントを1周やっていれば「こんなのあったなー」と思い出せるのでOK

あとは、機械学習の基本原則についての出題割合が30%〜35%といちばん高いので、ここは確実に取るためによく理解しておく必要がある

[責任あるAIの基本原則を確認する](https://docs.microsoft.com/ja-jp/learn/modules/responsible-ai-principles/)を理解出来ていれば問題はない、はず
docker for macでThe data couldn’t be read because it is missingのエラーが出る場合

#Dockerでfatal error

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700171/2a6f7e8d-be26-ad25-5e9a-f9398edea44b.png)

#やったこと

以下リンクから、docker 最新バージョン(この時は3.3.3)をダウンロード

https://docs.docker.com/docker-for-mac/release-notes/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700171/d40222b6-baea-01d8-85f6-ee4c7c7d5edc.png)


ドラッグ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700171/0a14ce34-46e6-ef28-a27d-5455c63495ff.png)

起動