OmniAICreator/Qiita-1.07M huggingface dataset:
Windows環境でGitLab for Dockerを立ち上げてみる

# 1. はじめに
* Windows環境でGitLab環境を構築した
* Dockerを使用してを環境を簡単に構築したい

# 2. 開発環境
* Windows 10
* Docker Desktop                                                           
* Docker Compose
* GitLab EE                                                                

# 3. Docker Desktopのインストール
## 3.1. インストーラーを起動し、ソフトウェアをインストールする
```
Docker Desktop Installer.exe
```                                         

## 3.2. Docker Desktop起動時に、「Docker Desktop requires a newer WSL kernel version」が表示された場合
* WSL Linux カーネルを更新する。
```
wsl_update_x64.msi
```

# 4. Docker Composeのインストール
## 4.1. PowerShellを管理者権限で起動する

## 4.2. 下記コマンドよりインストールする
```
Invoke-WebRequest "https://github.com/docker/compose/releases/download/v2.19.0/docker-compose-windows-x86_64.exe" -UseBasicParsing -OutFile $Env:ProgramFiles\docker\docker-compose.exe
```

## 4.3. 下記コマンドよりインストールを確認する                              
```
docker-compose --version
```

# 5. GitLabのインストール
## 5.1. 事前準備
* 下記フォルダを準備する                                                    
> C:\Docker\GitLab-ee
>   + config
>   + data
>   + logs

## 5.2. docker-compose.yamlの作成
* 下記ファイルを新規作成し、GitLab-ee直下に配置する
```YAML:
version: '3.6'
services:
  gitlab:
    container_name: 'gitlab2'
    image: 'gitlab/gitlab-ee:latest'
    restart: always
    ports:
      - '8080:80'
      - '2222:22'
      # 最初のPort番号で受けてDokcerへ後のPort番号で繋ぐ
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://[IPアドレス]:8080'                                                                                                                    ※IPアドレスは任意に変更する
        gitlab_rails['gitlab_shell_ssh_port'] = 2222
        nginx['listen_port'] = 80
        # Add any other gitlab.rb configuration here, each on its own line
    volumes:
      - 'C:\Docker\GitLab\config:/etc/gitlab'
      - 'C:\Docker\GitLab\logs:/var/log/gitlab'
      - 'C:\Docker\GitLab\data:/var/opt/gitlab'
    shm_size: '256m'
```

## 5.3. GitLabのインストール
* Docker Desktopを起動する
* PowherShellを管理者権限で起動する
* 下記コマンドでインストールを実行する
 ```
docker compose up -d
```
* 下記コマンドを実行状況を確認する
```
docker ps -a
```
* ブラウザで下記URLを開く
```
http://[IPアドレス]:8080
```
* Docker Desktopのターミナルからrootパスワードを確認する
```
cat /etc/gitlab/initial_root_password
```

# 6. Dockerコンテナの停止、削除方法
## 6.1. コンテナ停止
```
docker stop <コンテナ名>
```

## 6.2. コンテナ削除
```
docker rm <コンテナ名>
```

# 7. 参考文献

https://blogs.networld.co.jp/entry/2022/01/14/092636

https://qiita.com/ksh-fthr/items/6b1242c010fac7395a45

https://www.mathkuro.com/docker/expose-gitlab-on-different-ports/

https://www.gitlab.jp/blog/2022/05/27/initial-password/
Python 日本語変換モジュール "Utsuho"

私が開発している Python の日本語変換モジュール "Utsuho" をアップグレードしました。

https://pypi.org/project/Utsuho/

日本語を含むデータを取り扱う際に半角と全角、ひらがなとカタカナといった表記の違いに悩まされることは、よくあります。

例えば、日本郵便株式会社の郵便番号データ、総務省の全国地方公共団体コードといった住所関連のオープンデータは、住所の仮名表記が半角カタカナであったり、全角ひらがなであったりと統一されていません。

そんなよくある日本語の問題に対処すべく、私がオープンソースソフトウェアとして公開しているのが、"Utsuho" です。

日本語変換モジュールは、数多く公開されていますが、文字のマッピングがドキュメントに明記されていなかったり、必要以上に多機能であったり、業務で採用しづらいと感じることも多くありました。

"Utsuho" は、ドキュメントファーストで開発をおこなっており、文字のマッピングといった仕様がドキュメントに明記されています。現時点のドキュメントは、日本語で公開しています。

https://utsuho.readthedocs.io/ja/latest/

現時点の機能は、半角文字と全角文字の相互変換、ひらがなとカタカナの相互変換の 2 機能です。今後の機能拡充も、日本語の相互変換できる表記の違いに焦点を絞って、実施していく計画です。

又、Python モジュールとしてユーザーのアプリケーションへ組み込む以外にも、コマンドラインから直接利用していただけます。

```console
% utsuho half-to-full "ｷｮｳﾄｼ ｻｷｮｳｸ ｷﾞﾝｶｸｼﾞﾁｮｳ 2"
キョウトシ　サキョウク　ギンカクジチョウ　２

% utsuho katakana-to-hiragana "キョウトシ　サキョウク　ギンカクジチョウ　２"
きょうとし　さきょうく　ぎんかくじちょう　２
```

個人開発のため、至らぬ部分もあるかと思いますが、ご利用いただければ幸いです。プロジェクトへのコントリビュートも募集しています。

https://github.com/juno-rmks/utsuho/

私は、今後 "Utsuho" を使用して、住所文字列正規化の別モジュールを作成する予定です。

## 他製品との比較

全角から半角、及び半角から全角への変換を実現する他製品と比較してみました。

- jaconv
- mojimoji
- `unicodedata.normalize（'NFKC'）`

尚、`unicodedata.normalize（'NFKC'）` は、日本語変換モジュールではなく、Unicode データの正規化を実現する関数です。データクレンジングで使用されるケースも多いようなので、比較対象とします。

### 全角から半角への変換： jaconv と mojimoji との違い

jaconv　と　mojimoji は、結果が同じでした。utsuho との相違点は、次の通りです。

- 半角カタカナの定義があるワ行の `ワ` と `ヲ` の合成済み文字の濁音は全角のまま変換されません。
- 結合文字の濁音記号と半濁音記号の変換されずに結合文字として残ります。
- カタカナに続くかどうかは問わず、結合文字ではない単独の濁音記号と半濁音記号は全角のまま変換されません。
- 異体字セレクターは除去されずに残ります。
- 波線は全角のまま変換されません。全角チルダは半角へ変換されます。

全角カタカナの `ヷ` と `ヺ` は Unicode の katakana チャートに含まれており、半角カタカナに `ﾜ` と `ｦ` も定義されているため、utsuho では半角文字へ変換します。`ヸ` と `ヹ` は Unicode の katakana チャートに含まれていますが、半角カタカナに旧字体の `ヰ` と `ヱ` が定義されていないため、utsuho でも半角文字へは変換しません。

Unicode に結合文字としての半角の濁音記号と半濁音記号が定義されていません。utsuho では直前のカタカナと結合できる場合とカタカナに続くと判断できる場合に限り、全角の結合文字としての濁音記号と半濁音記号を結合文字ではない半角の濁音記号と半濁音記号へ変換します。

全角の疑問符や感嘆符は異体字セレクターを使用することで、フォントの実装によりますが、左右や中央揃えで表示することができるとされています。半角の疑問符や感嘆符には、その定義はありません。Utsuho では半角に定義のない異体字セレクターは除去します。

歴史的な経緯とフォントが似ていることから、日本語環境では波線と全角チルダは同等に扱われることが多いです。Utsuho では全角の波線も半角のチルダへ変換します。

### 全角から半角への変換： `unicodedata.normalize（'NFKC'）` との違い

`unicodedata.normalize（'NFKC'）` と utsuho の相違点は、次の通りです。

- カタカナと濁点、半濁点、句読点、鍵括弧、中黒、長音記号は全角のまま変換されません。
- 結合文字の濁音記号と半濁音記号は直前の文字と結合され、合成済み文字の濁音と半濁音へ変換されます。
  - 直前の文字との結合により、合成済み文字を形成できない場合は変換されません。
- 異体字セレクターは除去されずに残ります。
- 波線は全角のまま変換されません。全角チルダは半角へ変換されます。

`unicodedata.normalize（'NFKC'）`　は Unicode における正規化をおこなうため、全角カタカナを半角カタカナへ変換する機能はありません。同様に異体字セレクターの除去や厳密に同じとみなせない全角の波線の半角のチルダへの変換もおこないません。

結合文字を定義されている合成済み文字へ変換する処理は、Unicode における正規化に該当するため、実施されます。又、いわゆる ASCII コード範囲の全角のアルファベットと数字、記号も半角へ変換されます。
【SwiftUI】OptionalのBindingをアンラップする

# はじめに
Bindingの中身がオプショナルで型が違うので渡せないという問題に遭遇しました。
解決策を記録しておきます。

# 問題点
型が違うので渡せないわけですね
![スクリーンショット 2023-08-25 22.47.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/c9bd836c-5e36-7683-8c57-11703fc8b225.png)
```
Cannot convert value of type 'Binding<String>' to expected argument type 'Binding<String?>'
```
```swift
import SwiftUI

struct ContentView: View {
    @State var text: String = "サンプル"
    
    var body: some View {
        SubView(text: $text)
    }
}

struct SubView: View {
    @Binding var text: String?
    
    var body: some View {
        Text(text ?? "")
    }
}
```

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @State var text: String = "サンプル"
    
    var body: some View {
        SubView(text: .init(
            get: { text },
            set: { text = $0 ?? "" }
        ))
    }
}

struct SubView: View {
    @Binding var text: String?
    
    var body: some View {
        Text(text ?? "")
    }
}

```

# おわり
これは公式で対応してもらいたいですね
エクセルからテキスト出力するVBAをChatGPTに聞いた

エクセルからテキスト出力するVBA
```
Sub ExportDataToTextFile()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim outputString As String
    Dim filePath As String
    Dim fileNumber As Integer
    
    ' 出力先のファイルパスを指定
    filePath = "C:\出力先のファイルパス\output.txt"
    
    ' プログラム一覧シートを取得
    Set ws = ThisWorkbook.Sheets("プログラム一覧")
    
    ' 最終行を取得
    lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
    
    ' テキストファイルを開く
    fileNumber = FreeFile
    Open filePath For Output As #fileNumber
    
    ' ループしてデータを結合して書き出す
    For i = 2 To lastRow
        outputString = ws.Cells(i, "B").Value & " " & ws.Cells(i, "C").Value
        Print #fileNumber, outputString
    Next i
    
    ' テキストファイルを閉じる
    Close #fileNumber
    
    MsgBox "データをテキストファイルに出力しました。"
End Sub
```
【プラクティス紹介】1分でさらっと分かる「バリュープロポジションキャンバス」

![vpc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526800/95412b49-7abb-c3d7-57b8-8795684cc578.jpeg)

## プラクティス名（別名）
バリュープロポジションキャンバス　（VPC）

## プラクティスの目的・狙い
* 顧客ニーズと提供サービスにズレがないかを検証する

## どんな時に使うか
* 新製品/新機能/新サービスの企画検討時
（これから作るプロダクトが本当に必要とされるか確証が無い時）

## 実施手順
1. 「①顧客への提供価値」と「②顧客セグメント」を簡潔に一文で記入する
1. 「③顧客のしたいこと」⇒「④嬉しいこと」⇒「⑤嫌なこと」の順番で埋める
1. 「⑥提供する製品」⇒「⑦増やす要因」⇒「⑧減らす要因」の順番で埋める
1. 提供価値と顧客ニーズがマッチしているかをチェックする
1. ズレがあれば、製品やサービスの内容を再検討する

ビジネスモデルキャンバスの中にある、「顧客セグメント（CS）」と「バリュープロポジション（VP）」に特化したキャンバス。PSF/PMF（Prodct Solution Fit/Product Market Fit）を確認するための手法。

## アレンジ例
* 実際のエンドユーザにヒアリングしながら一緒にキャンバスを埋めていく

## アンチパターン
* 提供する製品を念頭において逆算で「顧客のしたいこと」書き始める
* 書いたことに満足してしまい、記載した顧客のニーズが本当に合っているかを検証しない

## 参考情報
出典の書籍

https://www.shoeisha.co.jp/book/detail/9784798140568

WEBではNIJIBOXさんのサイトの解説がコンパクトにまとまっていて分かりやすかったです。

https://blog.nijibox.jp/article/value_proposition_canvas/

## こぼれ話（私的コメント）
一目で見ただけで用途と使い方が分かるシンプルなキャンバスです。既存プロダクトへのちょっとした機能追加だと、ビジネスモデルキャンバスから書く、という展開にはならないので、これぐらいの軽いフォーマットの方が使いやすい気がします。これを一枚書いておくだけで、作った後でそもそも顧客ニーズに合ってなかったという事故に遭遇する可能性をだいぶ下げられるので、お守り代わりに使いたい一枚です。

　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)
cannot load such file -- ffi の解決法

<h1>エラーについて</h1>

Rails7環境上で画像投稿をしようとしたときにでたエラー

:::note alert
*LoadError in 〇〇sController#create
cannot load such file -- ffi*
:::


<h1>解決法</h1>

**Before**
```ruby:gemfile
# gem "sassc-rails"
```

**After**
```ruby:gemfile
gem "sassc-rails"
```

Rails Ver7からは上記の記載がコメントアウトされており、インストール時に適用されない。

コメントアウト解除後、

```ruby:cmd
bundle install 
```
により無事解決。
Laravelのemail(dns)バリデーションの動作がおかしかったので調べたら自分の環境が原因だった

# 結論
Laravelのemail:dns バリデーションは、DNSが設定されている環境、されていない環境で結果が変わることがある。本調査では、example.com（NullNXレコードが設定されている）ドメインについてバリデーション結果が変わることを確認した。

~~~ sh
# Before:DNSが設定されていない環境での実行結果
root@608e26d6b651:/var/www/html# php artisan tinker
Psy Shell v0.11.18 (PHP 8.2.9 ― cli) by Justin Hileman
> $v = validator(['email' => 'test@example.com'], ['email' => 'required|email:dns'])->passes();
= true
~~~

~~~sh
# After:DNSが設定されている環境での実行結果
root@608e26d6b651:/var/www/html# php artisan tinker
Psy Shell v0.11.18 (PHP 8.2.9 ― cli) by Justin Hileman
> $v = validator(['email' => 'test@example.com'], ['email' => 'required|email:dns'])->passes();
= false
~~~

# 関連
https://readouble.com/laravel/10.x/ja/validation.html#rule-email


# 発生現象
- Laravelアプリケーションのテストを書いてPRを出したところ、自分のローカル開発環境で成功するテストが、GithubAction上の仮想環境では失敗する、という現象が発生した。

# 調査過程のメモ
- ローカルでは成功しているのにGithubActionsでは失敗するテストは、いずれもEmailのバリデーションに関連するテストケースである。

- 各テストケースの入力値として「example.com」を使用しており、このドメイン名の名前解決が上手く行っていないのか？という仮説を立てて調査開始。

- 同僚に検証を依頼したところGithubActionで失敗するテストがローカル開発環境でも失敗するという報告をいただき、どうやら自分の環境がおかしい、ということになる。

## dns_get_record() の実行結果検証
- Laravel のバリデーション email:dns は[egulias/email-validator](https://github.com/egulias/EmailValidator)を使用している
- この中で、dns_get_record() を使っているので、artisan tinker 経由で結果を見てみることにする。

自分の環境では、結果が空配列になっている。
~~~sh
# 自分の環境
root@608e26d6b651:/var/www/html# php artisan tinker
Psy Shell v0.11.18 (PHP 8.2.9 ― cli) by Justin Hileman
> dns_get_record("example.com", DNS_MX);
= []
~~~


同じ検証を同僚の端末で行ったところ、MXレコードはない（target が空文字列となっている）が、結果自体は返ってきている。

~~~ sh
# 同僚の環境
> dns_get_record("example.com", DNS_MX);
= [
    [
      "host" => "example.com",
      "class" => "IN",
      "ttl" => 4667,
      "type" => "MX",
      "pri" => 0,
      "target" => "",
    ],
  ]
~~~


## DNS設定

https://tryota.hatenablog.com/entry/2021/01/10/Ubuntu20.04%E3%81%A7DNS%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B

こちらを見ながら、8.8.8.8と4.4.4.4を指定して、差分が解消した。

# 補足
- 結局、バリデーションを通過するテストケースはmxレコードが存在するemailを使用しなければならんのか？という問題が残る。テストケースに使うドメインは example.com 
- こっちのバリデーション https://readouble.com/laravel/10.x/ja/validation.html#rule-active-url も、DNS設定できない環境だと動作がかわる（かも？） ただ、example.comはAレコードは引けるので、関係ないかも。細かくは調査してない
【Python】終端記号を考慮して100文字までカットするコード

# 概要
与えられたコメントを最初の100文字までカットし、その際に特定の終端記号（句読点や記号など）が出現する最後の位置を考慮してカットを行うコードを実装しました。

# サンプルコード
## DBテーブルから取得しない場合：

```py
punctuation_mark = '。'

def cut_comment(comment):
    print("send_commentの文字数", len(comment))  
    comment_100 = comment[:100]
    print("send_comment_100の文字数", len(comment_100))  
    location = comment_100.rfind(punctuation_mark)
    print("locationの位置:", location)
    comment_100 = comment_100[:location + 1]
    print("send_comment_100:", comment_100)
    return comment_100


comment = 'コメントを100文字までにカットします1。コメントを100文字までにカットします2。コメントを100文字までにカットします3。コメントを100文字までにカットします4。コメントを100文字までにカットします5。コメントを100文字までにカットします6。'
cut_comment(comment)

# 出力結果:

# send_commentの文字数 126
# send_comment_100の文字数 100
# locationの位置: 83
# send_comment_100: コメントを100文字までにカットします1。コメントを100文字までにカットします2。コメントを100文字までにカットします3。コメントを100文字までにカットします4。

```

### .rfind() メソッドとは？
文字列内で指定された部分文字列を後ろから検索し、その最後に現れる位置（インデックス）を返すメソッド。

基本的な構文は次の通りです

```py
string.rfind(substring)
```

`string`: 検索対象となる元の文字列。
`substring`: 検索したい部分文字列。

このメソッドは、指定した部分文字列が見つからない場合には -1 を返します。それ以外の場合、指定した部分文字列が最後に現れるインデックスを返します。

### `comment_100[:location + 1]`
+1 を足しているのは、`location_punc_cd`が句読点文字の位置を示しており、その句読点文字を含めるためです。インデックスが0から始まるからですね。

## DBテーブルから取得する場合：

DBテーブル`PuncCd`には、以下のような形で登録されているとします。

```
id  punc_cd punc
1	1	    。
2	2	    ？
3	3	    ！
4	4	    .
```

```py
from xxx.models import PuncCd

def cut_comment(comment):
    comment_100 = comment[:100]

    # データベースから punc_cd の値を取得して data_punc_cd_values リストを作成
    punc_cd_values = PuncCd.objects.values_list('punc', flat=True)
    # punc_cd_valuesには<QuerySet ['。', '？', '！', '.']>が入ります

    location_punc_cd = None
    for punc_value in punc_cd_values:
        location = comment_100.rfind(punc_value)
        if location != -1:  # punc_valueが見つかった場合
            if location_punc_cd is None or location > location_punc_cd:
                location_punc_cd = location

    if location_punc_cd is not None:
        comment_100 = comment_100[:location_punc_cd + 1]

    return comment_100

comment = 'コメントを100文字までにカットします1。コメントを100文字までにカットします2。コメントを100文字までにカットします3。コメントを100文字までにカットします4。コメントを100文字までにカットします5。コメントを100文字までにカットします6。'
cut_comment(comment)
```

上記では、繰り返しの処理により、終端記号のリスト内で最後に出現する位置を探し、それを基準にコメントをカットしています。

丁寧に説明すると、以下のことを実施しています。

まず、`punc_cd_values`リスト内の各終端記号に対して、`comment_100`内でのその終端記号の最後の出現位置（インデックス）を `rfind`メソッドを使って探します。この位置を `location`として取得します。

もし `location` が -1 でない（つまり、その終端記号が `comment_100` 内で見つかった）場合、かつ、`location`の位置が既知の最後の終端記号位置 `location_punc_cd` より大きい場合、`location` を新たな `location_punc_cd` として更新します。これによって、最も後ろに位置する終端記号の位置が保持されます。

最後に、もし `location_punc_cd` が `None` でない場合（終端記号が見つかった場合）、`comment_100` を `location_punc_cd + 1`の位置でカットし、最終的なカットされたコメントを得ます。

ちなみに、`rfind`メソッドは文字列のメソッドであり、リスト（`punc_cd_values`）を引数として受け取ることはできません。そのまま渡すと以下のエラーになります。

```
'must be str, not QuerySet'
```
SQL② グループ集計、副問合せ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/139897c0-f836-7488-79bc-ebffa6ba1a5c.png)
　SELECT文は、検索結果をグループごとに集計して表示することもできます。例えば、「部門ごと」や「社員ごと」に平均値を計算したり、最大値・最小値を求めることができます。さらに、集計した結果について条件を満たすデータだけを表示することもできます。「部門ごとに平均を求めて、平均が〇〇以上の部門だけを表示する」という操作ができるわけです。これらの操作は、GROUP BY〜　HAVING句で行います。

　また、より複雑な検索として、副問合せがあります。副問合せは、SELECT文中に再度SELECT文を書いて、検索結果を元に検索するという方法です。副問合せを使うことで、一度も売れたこともない商品を検索したりできます。
関数を跨いだローカル変数の遅延初期化

# 問題点
lazy関数でローカル変数を遅延初期化する場合、その変数を関数の引数として渡すと、
関数の呼び出し先でその変数を参照しなくても、関数を呼び出す時点で初期化が実行されてしまう。（LazyインスタンスのgetValueが呼ばれてしまう）

```kotlin
fun main() {
    val value: String by lazy {
        println("initialize value")
        computeValue()
    }

    (1..3).forEach {
        process(it, value)
    }
}

private fun process(index: Int, value: String) {
    println("index: $index")
    if (index % 2 == 0) {
        println("value: $value")
    }
}

private fun computeValue(): String {
    Thread.sleep(3000)
    return "Hello"
}
```
結果
```
initialize value
index: 1
index: 2
value: Hello
index: 3
```

# 解決策
lazyなプロパティを保持するクラスを作成し、関数の引数として渡す。

```kotlin
class LazyValueProvider<T>(initializer: () -> T) {
    val value: T by lazy {
        initializer()
    }
}

fun main() {
    val provider = LazyValueProvider {
        println("initialize value")
        computeValue()
    }

    (1..3).forEach {
        process(it, provider)
    }
}
}

private fun process(index: Int, provider: LazyValueProvider<String>) {
    println("index: $index")
    if (index % 2 == 0) {
        println("value: ${provider.value}")
    }
}

private fun computeValue(): String {
    Thread.sleep(3000)
    return "Hello"
}
```
結果
```
index: 1
index: 2
initialize value
value: Hello
index: 3
```
プログラミングスクール卒業後のあれこれ

約5か月ぶりにQiiitaを更新します。

2022年7月～2023年1月までプログラミングスクールに在学し、
HTML/CSS、Rails、GitHub、AWSなどなどなど様々な学習をしてきました。

Qiitaにはアウトプットのために投稿をしていましたが、その後の自分の生活について振り返ってみようと思い、久しぶりに書いてみます。
といっても、一気にはかけないので少しずつ書き留めていきます。

簡単に自己紹介
- 30代前半
- 2児の母
- 地方在住
- これまでの職種は営業、営業事務など


# スクール卒業・転職活動について
スクール卒業間近から本格的に転職活動がスタートしました。
私は地方在住かつ、家族の仕事の関係で、引っ越しなどはできないため、今住んでいるところから通えるor在宅で働けるような職場を希望していました。

しかし、それではあまりにも会社が絞られすぎるため、東京の企業も見ていました。
東京であれば週に1～2回の出社ならできそうかなと考えたためです。

選考や面談をした企業は4社。
東京の企業3社、自宅から通える企業1社。

色々な企業の方と面談して率直に思ったこと。
未経験でエンジニア就職、たまに都会に出社、子育て、家事、これ全部こなせるんか？
ということですね。
未経験エンジニアで在宅の求人はあまり無い（それに自分自身不安）だし。
採用の方も、育児と両立が大変だと思いますよ・・とのこと。
逆に、ワークライフバランス整っていますよとおっしゃっている企業さんもありましたが、
働いている方の話を聞いているととても大変そうに思い本当か？と思うことも。

とはいえ、キャリアアドバイザーの方に支えられて、自己分析や面接練習をこなし、無事に就職先が見つかりました。
職種はエンジニアではないですが、システム部門が立ち上がり、色々なことに挑戦し、会社の基盤整備をこれから本格的にやっていこうというような部署です。
まずはシステムサポートからやっていきましょうか、というポジションでした。

就職後、様々な経験が出来ました。
内容はまた次の記事で書きたいと思います。


## あとがき
補足として書いておきます。
転職活動する中で、エンジニア職・家事・育児などこなせるのか？という不安な気持ちが募り弱気になっていました。
じゃあスクールを受講した目的は？と聞かれれば、最初は夫の勧めでした。
育休中に資格取得やAdobeソフト（イラレ・フォトショなど）の勉強をコツコツしており、クラウドソーシングサービスを利用して少しお仕事もしていました。
しかし、独学に限界を感じている部分もありました。
なにか1つでもしっかり勉強してスキルアップにつなげたい、それをキャリアに活かしたいという気持ちがありました。
なによりも、家事育児だけでなく、自分自身の今後についても見つめ直したい。
そんなときに夫からプログラミング勉強してみたら？と。
自分の人生には関わりのない業界とも思っていましたが、無料でプログラミングを体験できるサイトを利用してみたり、様々なサイト、子どものプログラミング学習の記事などを見ると興味を持ちました。
色々な思いを巡らせていましたね。
結果、育休後の転職活動につなげられたので良かったと思っています。
[UE5] Procedural Content Generation(PCG)を触ってみた①

![HighresScreenshot00000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/151430f8-0197-d31b-73ca-54171a136a7f.png)
## 今回はUnreal Engine 5.2の新機能PCGのグラフとノードを簡単に紹介する記事です。
> PCG(Procedural Content Generation)とは、ノード形式でシーンを動的に作成できる機能です。
## 準備

1) PCGのプラグインをオンにして再起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/bdccc3e1-5a6b-3b57-7e5f-724b30fec732.png)
2) ランドスケープと配置用のアセットを用意します(試したところLandmassとの併用可)

>本記事はこちらのアセットパッケージを使用しました。
>https://www.unrealengine.com/marketplace/ja/product/advanced-village-pack

3) PCGVolumeをマップに追加し、PCG Graph Instanceを作成しアサイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/0e7293fe-a7b8-a711-bcac-491a00ea6fef.png)
準備が整ったらGraphアセットを開きます


## ノード解説

シンプルなグラフで少しずつ説明していきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/9750edf8-d882-edda-5a61-f074b62160b8.png)
ランドスケープにメッシュをランダムな位置に配置するグラフ

### 1) Get Landscape Data 
　ランドスケープのデータを取得するノード。グラフのInputノード→Landscapeを使っても同じ効果がありますが、UE5.3ではDeprecatedとなっているため専用ノードを使います。
	
### 2) Surface Sampler
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/db8dda07-3a70-347c-1615-dc85760c6a81.png)
 Surface(ランドスケープ入力)からランダムの点群を作成するノード。
 
 Extent入力は自作Vector関数で、一つのポイントのサイズを調整しています。関数にしなくてもグラフ内で設定できますが、関数にすればアクターから直接に調整できるようになります。
 
 ポイントのランダム性を調整するパラメーター：
- Points Per Squared Meter (1平方メートルで何回ポイント配置するのか、１より下の数字は確率になります)
 - Looseness(配置の緩さ？サンプリングスケールみたいなもので、大きければ配置の全体スケールが拡張されます)
 
Point Extents より小さく配置されないので要注意です
（追記：Point Extentsをメッシュのサイズにするときれいに配置できる場合が多いです）
 
### 3) Transform Points
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/0a81cbbf-26ba-ef30-ca03-862fd9dd0b67.png)
ポイントをさらに微調整するためのノード。ここではZ軸の回転をランダムになるよう調整しました。
Absolute にチェックを入れていないので調整していない数値はSurface Samplerから引き継がれます。

### 4) Static Mesh Spawner 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/312ab0f1-37a5-daee-d92d-dd5bdc20a5ee.png)
ポイントの位置にメッシュを配置するノード。ここでは草のメッシュを３種類用意しました。この３種類のWeight値で配置されるメッシュが決められます。全部１の場合は均等に配置されます。

以上の実行結果がこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/06e4d6ee-304f-c789-e462-b3d17dda08f6.png)

以上のグラフを別のメッシュで重ねて設定し、
ポストプロッセスを調整したら簡単にミステリアスな森が作れます

グラフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/0512179b-01e4-10eb-08a3-c637c3068dcb.png)
>Extentサイズや密度が違うメッシュでは個別のSurface Samplerで設定を変えています

最終結果
![HighresScreenshot00000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3264403/151430f8-0197-d31b-73ca-54171a136a7f.png)

## 終わりに
　簡単なグラフでここまでできてシーンのブロックアウトがしやすく、極めれば非常に強力なツールだと感じました。今回はPCGの一番基本な部分しか触れておらず、スプラインに沿って配置することや、Blueprintとの連携など複雑なこともできますので、今後の記事でまた他の機能も紹介したいと思います。
Typescript✖️Vue3で、props,emits

# Typescript✖️Vue3でpropsとemitsがしたい

参考記事
https://zenn.dev/aoito/articles/a09eb484344ae2

## definePropsのつかいかた
親から子へ
``` vue:親コンポーネント.vue
<template>
  <child :title="Title">
</template>

<script setup lang="ts">
import child from "子コンポーネント.vue"

const Title = 'あああ'
</script>
```
``` vue:子コンポーネント.vue
<template>
  <h1>{{ title }}</h1>
</template>

<script setup lang="ts">
const props = defineProps<{
  title: string
}>()
</script>
```

## defineEmitsのつかいかた
子から親へ
``` vue:子コンポーネント.vue
<template>
  <button @click="onChange(false)">閉じる</button>
</template>

<script setup lang="ts">
const emits = defineEmits<{(e: 'click', value?: boolean): void}>()
const onChange = (value?: boolean): void => {
  emits('click', value)
}
</script>
```
``` vue:親コンポーネント.vue
<template>
  <child v-if="isActive" @click="onChange" />
  <button @click="changeActive">子コンポーネントを表示する</button>
</template>

<script setup lang="ts">
import child from "子コンポーネント.vue"

const isActive = ref<boolean>(false)
const onChange = (val?: boolean) => {
  isActive.value = val;
}
const changeActive = () => {
  isActive.value = true;
}
</script>

```
AWS ECS – CodeDeploy での blue/green デプロイで テスト用のポートは公開されていなくても良いのか？ Webからアクセスできなくても良いのか？

# 問題

AWSのCodeDeployではデプロイグループの設定で「本稼働リスナーポート」と「テストリスナーポート」が設定できる。
だがここでの疑問は「テストリスナーポート」はどのようにテストされているのかということだ。

トラフィックをテストするということは何かしらの形で外部からアクセスが来るものだと思うのだが。
試してみたところ思ったのとは違う挙動を見せている。

たとえば ポート 10000 をテストリスナーポートに指定した場合、Webから アクセス出来なくても blue/greenデプロイが成功する。
( 例: `http://example.com:10000/` )

この動きが分からない。

デプロイ設定に ECSAllAtOnce を選んでもそれ以外を選んでも成功する。
どうやらテスト用のポートには必ずしも外部からアクセスできる必要ないような気がしてきた。

( そもそも何かを根本的に理解し間違っているかもしれない )



<!--

すると ALBのリスナールール ( この例だと ` HTTPS:10000` )  で blue/greenデプロイのたびにリスナーに紐づくターゲットグループ(ターゲットグループへ転送)が変わるではないか。

どうやらちゃんと「付け替え」がおこなれているようだ

-->

# 動作確認

AWSのセキュリティグループ・ALBのリスナー・ターゲットグループの指定などを変えて `http://example.com:10000/` にブラウザからも直接アクセスできるようにしてみた。

そして以下のデプロイ設定でblue/greeenデプロイの挙動を試してみた

```
CodeDeployDefault.ecs PercentEvery
すべてのトラフィックが移行されるまで、毎分トラフィックの 10 パーセントを移行します。
```

デプロイが進捗中にALBのリスナールールのページを見てみると、本番稼働用のリスナールールでは以下のようにターゲットグループの「比重」が変わっていくのが分かる。

```
ターゲットグループへ転送
target-1: 90 (90%)
target-2: 10 (10%)
```

```
ターゲットグループへ転送
target-1: 80 (90%)
target-2: 20 (10%)
```


```
ターゲットグループへ転送
target-1: 70 (90%)
target-2: 30 (10%)
```

これはデプロイ進捗画面の「トラフィック移行の進行状況」と同じものを表しているみたいだ。

<img width="531" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/800c5e42-b0df-4dac-b203-5f3c09c24acc">

デプロイ設定にもよるがリスナーに紐づくターゲットグループの比重が変わって行くのがAWSのblue/greenデプロイの動きのようだ。

# blue/greenデプロイ中にWebからアクセスしてみると

デプロイ中にWebからアクセスしてみると以下の動作が確認できた

## 本番稼働用のURLでは

新しいバージョンのページ/古いバージョンのページがランダムに表示される
(画面リロードするたびにどちらかに振り分けられる)

その時のトラフィックの比率に対応してどちらに振り分けられるかの確率が変わっていくようだった。
たとえば 「ターゲットグループA 90%」「ターゲットグループB 10%」 のトラフィック割合の時にアクセスすると 10回中9回は前者にアクセスが振り分けられていた。

##  テストリスナー用のURLでは

常に新しいバージョンのページが表示される


# AWSの説明を再確認してみる


```
テストリスナーポート - オプショナル
トラフィックによって再ルーティングされる前に置き換えバージョンをテストする場合は、テストリスナーが必要です
```

ここでいう「置き換えバージョンをテストする」というのはblue/greenデプロイによるテストではなくて、我々が何かしらのテストをする場合ということなのだろうか？

どうやらそういうことなのかもしれない。

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/tutorial-ecs-deployment-with-hooks.html

>このチュートリアルでは、Lambda 関数を使用して、更新された Amazon ECS アプリケーションのデプロイの一部を検証する方法について学びます。

>検証テストを追加するには、最初に Lambda 関数でテストを実装します。次に、AppSpecデプロイファイルで、テストしたいライフサイクルフックのために Lambda 関数を指定します。検証テストが失敗した場合、デプロイは停止し、ロールバックされて、失敗とマークされます。テストが成功すると、デプロイは次のデプロイライフサイクルイベントまたはフックに進みます。

blue/greepデプロイでトラフィックの比重が変わっていく挙動とは別に、テスト用のリスナーを使って最新バージョンをテストできるということなのかもしれない。


# 結論

- テスト用のリスナーポート設定はあくまでオプショナル。指定しなくてもblue/greenデプロイは出来る。
- テスト用のリスナーポートにWebからアクセスできるように設定しておくとデプロイ時の最新バージョンを確認できる。
- 本番稼働用のトラフィックは片方のターゲットグループからもう片方のターゲットグループへとALBリスナールールの比重がシフトしていく (なのでテストリスナー用のポートは関係なさそう)

これは現段階での理解だがまだまだわからない部分が多そうだ。


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
gather.town コマンド集

個人用メモ

# コマンドリスト

|実行コマンド|処理|
|-|-|
|game.players| ユーザー一覧取得|
|gameSpace|スペース情報取得|
|gameSpace.gameState.ユーザーID|ユーザー情報取得|
|gameSpace.mapId| 今いるマップID取得 |
【Unity】ほかの学生さんに見て欲しい！大学生がUnity認定試験に挑戦した話

# 自己紹介
大学２年生のUnity大好きマン。
## 注意
- 今回の記事はいつもよりエゴが強いので気を付けてください。
- この記事は2023/08/25に受験した体験をもとに書いています。

# Unity認定試験とは
Unity公式が提供する資格試験のこと。
Unity Japan主催のゲームジャムに参加したときに激おしされた。たぶん公式が力入れてるやつ。

## 詳しくはこちら

https://unity.com/ja/products/unity-certifications

# 今回受けた試験
私は、お試しということもあってアソシエイトという中等教育以降および意欲的なプロフェッショナル向け（公式サイトより）のプログラマーカテゴリの試験を受けてきました。

# 勉強方法
ごめんなさい。勉強してないです…
ただ、どの程度の難易度か知るために公式の模擬テストを2回受けました。

## 公式の模擬テスト
全部英語です。2~5問程度言語によって間違えた問題がありました。
それを含めても8割程度は初見でも解けたかなという所感です。

基礎的な問題が多かったです。

## 独学の壁
私は中学から独学でUnityをやっており、参考書は一冊も持っていません。
~~最近Unity Test Frameworkの本を一冊買いましたが…テスト範囲外なのでカウントしないということで~~
そのため、以下のような実用場面で使われない知識を問われる問題は苦戦しました。
- Ivoke関係
- PlayerPref
- Physics Material

最後のPhysics Materialについては便利そうなので場面があれば使いたいと思っていますし実用的なのかもしれません…が、上2つは…
IvokeはUniTask大先生に頼ったほうが書きやすいですし、PlayerPrefも（正直何も知りませんが）不便があると聞きます。
こういう実践には…というものも聞かれることが独学で勉強した人にとっては難しいですかね。

# 試験を受けて
試験を受けて思ったのは、模擬試験より難しくね？ということです。
特に不合格になりそうとまではいきませんでしたが、それでも難易度絶対に本番のほうが高かったように感じます。

具体的には応用問題が多かったですね。最適化の話などは模擬テストでは出なかったように思います。
注意してほしいのは、模擬テストもそこまで数を回していないことです。
問題の偏りがあった場合もあるので、一概に模擬テストより難易度が上がるということはないでしょう。

## Unityのバージョンの話
試験を受けていて、Prefab関連の問題があったのですが、明らかに画像が古い！！
これ、あとから知ったのですが、Unity 2019 LTSを基準に作問されているようで、Prefab valiantの画像が古かったです。
正直、既に2022も出てるし問題のバージョン上げてほしい…！

## 余談：テストセンター
テストセンターってあんな感じなんですね。
私が行ったところは入り口入りにくすぎてビビりました。

# この記事で本当に伝えたいこと
長々と感想を喋ってきましたが、本当に伝えたいのは次の奴です。

## （特定の教育機関の）学生ならこの試験無料！！
この試験普通に受けると4万円ぐらいするんですよね。
ですが、UAA（Unityアカデミックアライアンス）を持つ大学などの教育機関に在籍しているとこれが無料になります。

もちろん、大学につき何人までというような制限はあるようなので、しっかり関係各所に確認を取ってみてください。

# 正直な話
この資格、3年間で失効します。そのため、資格としては結構有用なのかと思っています。
しかし、まだ就活もしていない身ですから企業にとってどれだけ魅力的なものなのかは全くの未知です。

また、内容も必ずしも実践的とは言えません。もちろん実践で使えることのほうが多いですが…
そのため、Unityを昔からやっていて余裕がある人や、一通りゲームを作ってみた人で目指す先が不透明になった人などが目指してみるといいと思います。
これに当てはまれば、そこまで難しくない試験です。

逆にUnityのスキルを高めたいからという理由で受験するのはオススメできません。
絶対にUnityを実際に触る時間を増やしたほうが実践的な勉強ができるでしょう。
特にアソシエイトぐらいの難易度であればゲームを作っている段階で十分に習得できるはずです。

# まとめ
と、、、まぁなんやかんやで上から目線で喋りましたが、そんなことはどうでもいいんです。
なんとなんといっても無料で受けれる可能性があるものです。

実際の体験として、、、
私がUnity公式の人とお話して、大学に問い合わせてみたところ、**大学側はこの制度を把握しておらず**、大学がUnityに問い合わせて手順を作って…やっと無料の恩恵を受けれたものです。
そのため、無料で受けれるという事実を知ってほしいと思って書いてみました。

ぜひ興味がある人は大学に問い合わせてみてください。

# さいごに
最後に、私が勝手に色々お問い合わせして関係各所のお仕事を増やして申し訳ありませんでした。
協力してくれた大学の方々には感謝してます。ありがとうございます。

そして、ここまで読んでくれた方でUnityの認定試験に挑戦してみる方が少しでも増えればうれしいです。
ぜひ頑張ってください。私も頑張ります！

NEXT Unity Professional Programmer!
合格目指すぞ！
AWS CLIのIAMユーザーのターミナルでの設定方法

## 概要
- AWS LambdaとDynamoDBを使ってLINE Botを作ったので、その備忘録の1つです。
- この記事では、実装したLambdaのコードを自動デプロイするための、CLI用のIAMユーザーをターミナルで設定する手順を説明します。

## 環境
macOS: 13.5.1
Homebrew: 4.1.4
aws-cli: aws-cli/2.13.7 Python/3.11.4 Darwin/22.6.0 source/arm64 prompt/off

## 前提条件
- [AWS CLI](https://aws.amazon.com/jp/cli/)のダウンロード・インストール済み
- CLI操作用のIAMユーザーを作成済み。
    - IAMユーザーの作成方法は [以前書いた別の記事(CLI&コンソール作業用のAWS IAMユーザーを作成する)](https://qiita.com/zono345/items/d1934a812c88b655364a) を参照のこと。
- macOSであること。
    - Windowsの場合は、手動でコードをzip化して、手動でLambdaへアップロードしてください。

## 事前準備
- IAMユーザーを作成した際にメモをした `Access key ID` と `Secret access key` を手元に準備しておくこと。 

## 設定方法
- ターミナルを開き、 `aws configure --profile dev_cli` を入力。指示に従って以下を入力。
    - AWS Access Key ID: メモから転記
    - AWS Secret Access Key
    - Default region name: 今回は `ap-northeast-1` で設定。
    - Default output format: `json` を設定

```bash
aws configure --profile dev_cli
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: YYYYYYYYYYYYYYYYYY
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

- これでローカルPC内のAWS CLI設定ファイルへのIAMユーザー情報の追加ができました。
- 次に、Lambdaのコードをアップロードするディレクトリで、IAMユーザーのアカウントを `dev_cli` に設定します。
```bash:my-project/my-function
export AWS_DEFAULT_PROFILE=dev_cli
```
- これで設定完了です。

## 補足情報
- **補足情報1**
    - ちなみに、ターミナルで設定したIAMユーザーの設定は、以下のコマンドで確認できます。
    - `aws configure list --profile {user_name}`
```bash
aws configure list --profile dev_cli
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                  dev_cli           manual    --profile
access_key     ****************IKXA shared-credentials-file    
secret_key     ****************m+C1 shared-credentials-file    
    region           ap-northeast-1      config-file    ~/.aws/config

```

- **補足情報2**
    - 設定したIAMユーザーをローカルPCから登録解除したい場合は、AWS CLIが設定ファイルを保存しているディレクトリに移動し、関連する設定を手動で削除する必要があります。
    - `credentials` と `config` を修正します。各ファイルへ格納されている情報は以下の通りです。
    - `credentials` : AWS Access Key ID, AWS Secret Access Key
    - `config` : Default region name, Default output format
```
~/.aws/credentials
~/.aws/config
```
ボタンをクリックして、v-bindで画像を切り替える(Vue3)

v-bindで画像を切り替えようとしたらできない。なんでや。。。

メモ書き
＊＊＊

画像の格納先をassetではなく、publicに置いたらできた。

```vue:index.vue
<template>
  <img :src="Img">
  <button @click="changeImg">変われ</button>
</template>

<script setup lang="ts">
import { ref } from 'vue'
// 画像はassetではなく、publicに置く
const Img = ref<any>('/first.svg')
const changeImg = () => {
  Img.value = '/second.svg';
}
</script>

```

＊＊＊
これでもいけるかも

```vue:index.vue
<script setup lang="ts">
import firstImg from '../../asset/first.svg'
import ｓecondImg from '../../asset/second.svg'

</script>
```
Proxmox8 を試してみる　その１２　WOL(Wake-on-LAN)の設定

# Proxmoxで WOL(Wake-on-LAN)
WindowsのVMWareでサーバ運用していたPCを、Proxmox へ移行したのですが不用意にシャットダウンしてしまい [Wake On Lan](https://ja.wikipedia.org/wiki/Wake-on-LAN)(以下 WOL)で起動できなかったときのメモです。

すっかり忘れていました。WOL を使用するためには、以下が必要です。
　・BIOSによる WOL の 有効化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/e3e99f3b-d2b6-0867-da49-dd7b0da5c19c.png)
　・OS側による WOL の 有効化

特に今回は、使用してたPCのOSを Windows から Linux に変更したこともあり、設定するのをすっかり失念していました。

# WOL(Wake On Lan) とは
ネットワーク経由(物理)で起動したいマシンに "マジックパケット" を送信することで、そのマシンの電源をONにする機能です。特にサーバ機器の場合、遠隔地もしくは目に見えない場所においてあることもあるため電源が落ちた場合、立ち上げに苦労するのためこの WOL を有効化する意味があります。

# WOL(Wake On Lan) を使えるLANポート
USB-LANでも使用することができるみたいですが、ハードウエアに付属のLANポートもしくはPCIに直刺ししたLANポートが良いと思います。

## NIC の MACアドレス
`ip a` コマンドを実行してNIC の MACアドレスを確認します。仮想マシンを複数作成している場合、かなり情報量が多く表示されますが 大概先頭のほうに「enpｘｘｘｘ」と表示されているのが知りたいNICのデバイス名とMACアドレスになります。


```
# ip a
2: enp1s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vmbr0 state UP group default qlen 1000
    link/ether ee:4f:ee:e8:ee:92 brd ff:ff:ff:ff:ff:ff
```

:::note info
上記から判ることは
　デバイス名：enp1s0f1
　MACアドレス：ee：4f：ee：e8：ee：92
:::

## NIC が WOLに対応しているか
冒頭でもありましたように LANポート(NIC) が WOL(Wake On Lan) が使用可能か否かを確認します。そのために `ethtool` をインストールします。


```
# apt install ethtool
```

先ほど調べたNICのドライバ名を指定してみます。

```
# ethtool enp1s0f1 | grep -i wake
```

結果として以下となります。注目して欲しいのは、「Wake-on」が 'g'（有効） となっていること。以下の例では 'd'（無効） となっています。


```
        Supports Wake-on: pumbg
        Wake-on: d
```

## WOLを有効にする、そして半永久的にｗ
厄介なのが「'g'（有効）が有効化されるのは次回起動時のみ、次々回以降はWOLが無効になります。」という仕様らしい。ですので半永久的に'g'（有効）に設定します。


・[ubuntuでWake On LANを設定する](https://tarufu.info/ubuntu-wake-on-lan/)

まず。 'g'（有効）にします。※現在の値が 'g'（有効） でも構わずやります。

```
# ethtool -s enp1s0f1 wol g
```

結果は・・・

```
# ethtool enp1s0f1 | grep -i wake
        Supports Wake-on: pumbg
        Wake-on: g
```

crontabに登録します。これで毎回実行されるようになります。


```
# crontab -e
・
・
・
@reboot /usr/sbin/ethtool -s enp1s0f1 wol g

```

お試しで電源OFF,,WOL で・・・・。起動！！

# WOLツール
Linux ですと `wakeonlan` コマンドを利用できます。Windowsではツールがありそうなのでそれを使用するのもいいかもしれませんね

・[nWOL: Wake on LANを使った遠隔PC起動管理ツール](https://n-archives.net/software/nwol/)
・[マジックパケットとは？PowerShellでWakeOnLanを起動するコマンドの作成方法](https://nw-engineer.work/wol/)

# 参考にさせて頂いたサイト様
・[ProxmoxでのWOL(Wake On Lan)起動で個人的につまずいたところ個人メモ](https://ragy.work/?p=27)
・[Enable Wake On LAN on Proxmox/Debian](https://i12bretro.github.io/tutorials/0608.html)
ViewInspectorを使用したWebViewテストの雛形

[ViewInspector](https://github.com/nalexn/ViewInspector)でWebViewのテストを書こうとしてハマったので備忘録。

作成したサンプルコード

https://github.com/mbotsu/WebViewExample

どの辺でハマったか。

## UIViewControllerに処理を書かないと始まらない。

`UIViewController`の`viewDidLoad`を実行するには、`view.loadViewIfNeeded()`を実行しないと処理が始まらない。
当然ViewInspectorもUIViewControllerを取り出さないと処理が始まらない。

```swift
sut.on(\.didAppear) { view in
  let uiView = try view.view(WebUIViewControllerRepresentable.self).actualView().viewController()
  uiView.loadViewIfNeeded()
}
```

## Viewに書いたdidAppearが機能しなくなる

ContentViewにenvironmentObjectを設定するとdidAppearでエラーが出るようになりました。

```swift
struct ContentView: View {
  var didAppear: ((Self) -> Void)?
  var body: some View {
    VStack {
      WebUIViewControllerRepresentable()
    }
    .padding()
  }
}
```

```swift
// こう書くとdidAppearが機能しない
var sut = ContentView().environmentObject(param)

// 正しくはこうする
var sut = ContentView()
ViewHosting.host(view: sut.environmentObject(param))
```

## 処理の完了通知を受け取りたい

もう少しいい方法あるだろうけど簡易なもので。

```swift
// ObservableObjectでVoidを作成
class Param: ObservableObject {
  @Published var exception: (String) -> Void = { _ in }
}

// テスト完了通知のクロージャーを作成
let exp = XCTestExpectation(description: "didAppear")
let param = Param()
param.exception = { message in
  XCTAssertEqual(message, "complete")
  exp.fulfill()
}

// HTMLを読み込んだら完了通知
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    if isRunningTests() {
      parent.param.exception("complete")
    }
}
```


## おわりに

以上です。
ViewInspectorでWebViewのサンプルコードを見かけなかったので書いて見ました。
無駄に時間を使う人が減れば幸いです。


## 追記

`UIViewController`を`UIViewControllerRepresentable`に統合して最適化したところ、`loadViewIfNeeded`を呼ばなくても動作するようになった。
それでいいのか？

## コード

ファイル数が少ないので掲載。
小さいコードに構造まとめるの大事ですね。

https://gist.github.com/mbotsu/41bb1dd4e2cd659478f4f685b4c183fb
ORMの概念理解

## 目次
1. ORMとは
2. NO ORM vs ORM
3. ORMの利点と欠点

##  ORMとは?
オブジェクト関係マッピング(ORM、Object-Relational Mapping)は、オブジェクト指向プログラミングと関係データベースの互換性を向上させるために設計されたプログラミング技術です。ORMの基本的な構造は、プログラミング言語のクラスとデータベースのテーブルをマッピングすることから始めます。これにより、エンジニアは直接SQLクエリの作成することなく、ORMを通じてデータベースと相互作用できます。

## NO ORM vs ORM
実際、どういう意味なのかは具体的な例を見れば分かりやすいと思います。 まず、簡単な2つの例を見ながら違いを感じてみてください。

##### ORMを使わない例 - 直接データベース操作

```ruby
users = Array.new
sql = "SELECT * FROM users"
rows = some_sql_module.query(sql); # `some_sql_module`は簡略化された例
rows.each do |row|
    user = User.new;
    user.id = row[:id] # シンボルがカラム名として使用されると仮定
    user.name = row[:name]
    user.email = row[:email]
    users << user
end
```
このコードは、Rubyでデータベースからユーザーのリストを取得する例です。
**`sql`** 変数にはSQLクエリが格納されており、**`some_sql_module.query(sql)`** を使ってデータベースからデータを取得します。取得された各行は、新しい User オブジェクトにマッピングされ、そのオブジェクトの各属性（**`id`**、**`name`**、**`email`**）がデータベースのカラムに対応します。最後に、ユーザーのオブジェクトを **`users`** 配列に追加します。このコードは、ORMなしでデータベース操作を行う典型的な例です。

上記のコードをRailsのORM、ActiveRecordを使用すると、同じ操作が極めて簡単になります。クエリの全てが抽象化され、以下の1行で実行できます。次の例を見てください。

##### ORMを使う例 - RailsのActiveRecord

```ruby
users = User.all
```

この1行のコードは、上記のRubyコードで行っていた操作と同じですが、Railsの**ActiveRecord**を使用しています。ここでは、**`User.all`** メソッドを呼び出すだけで、データベースから全てのユーザーを取得し、Userオブジェクトの配列として **`users`** 変数に格納します。

上記の2つの例を絵で構造化して表現してみましょう。

![Screen Shot 2023-08-25 at 20.18.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3529304/8ce979fb-1bfb-4fec-1393-c556ef8dcc54.png)


このシンプルな例からも、ORMを使うことで、データベースとの対話がどれだけ簡単かがわかります。コードの可読性が上がり、保守も容易になります。しかし、ORMはあくまで抽象化のレイヤーなので、特別なケースや最適化が必要な場合は、直接SQLを書く必要があることもあります。

## ORMの利点と欠点
今までORMが何なのか具体的に見てきました。 それではここでORMの利点と欠点を簡単に整理します。

#### 利点
- コードの再利用性: モデルクラスを通じたデータ定義により、コードの再利用と保守が容易になります。
- 開発効率の向上: 自動化されたクエリ生成により、開発時間の短縮とデータベース操作の簡素化が可能です。
- データベース独立性: 抽象化されたレイヤーを提供することで、異なるデータベースへの移行が容易になります。
- オブジェクト指向的なアプローチ: オブジェクト指向プログラミングの特性をそのまま活用できます。


#### 欠点
- 学習曲線: 特定のORMライブラリの使用法と動作方式を学ぶ必要があります。
- 複雑なクエリの問題: 非常に複雑なクエリを扱う場合、直接SQLを使用する必要があります。
- パフォーマンス問題: ORMの内部動作やクエリの最適化失敗などからパフォーマンスの問題が発生することがあります。


## まとめ
ORMは開発の効率を向上させ、コードの再利用性を高める重要なツールですが、全てのプロジェクトに適合するわけではありません。その特性と制約を正確に理解し、プロジェクトのニーズと合致するかを慎重に評価することが重要です。この記事が少しでもORMの概念を理解するのに役立つことを願っています。

## 参考文献
- Rochester Institute of Technology, ORMs, https://www.se.rit.edu/~swen-344/slides/DB/rabb/03.5-ORMs.pptx
疲れを飛ばせ！猫の画像を取得して癒しを得る方法

# まず初めに

最近、疲れてるなーと思って、夏バテかな？って思ったり思わなかったり。
そんな時に我が家の猫に癒されてます。

猫は正義！！

あ！そうだ！猫の可愛さを広めたいと思った矢先、あるじゃないですか。
猫の画像をランダムでくれるAPIが。(笑)
世間は色々なものに溢れてますね。

その素晴らしいサービスの名前が、TheCatAPI！

# The Cat API - Cats as a Service. 

面白いですね。SaaSやPaaS・IaaS等色んなサービスがある中で、
なんと初となる？CaaSですね。

[The Cat API - Cats as a Service. ](https://thecatapi.com)

猫の画像を引っ張ってきて癒しをもらおう企画開始！
猫好きの皆さんは手軽に可愛らしい猫の画像を楽しむ？ことができます？

# TheCatAPIのAPIキーの取得

ここは正直、なんやかんやでやってくれ。(笑)
大体皆察してると思うので、割愛。
色んなサービスと同じで登録と取得です。

# FileMakerの準備

まぁ例のごとく適当に適切だと思うようにテーブルやフィールドを作ってくだせぇ。
後はスクリプトステップURLから挿入スクリプトでなんやかんやしてください。

私はとりあえずQuick start欄からClick on this to get a random Imageを作りました。

![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363465/ca8504b7-da50-0433-6cb4-3e6926ee562c.jpeg)

はい。可愛いー。
いやぁ。いいっすね。猫は無害。
~~これを見た、人間に疲れた~~猫好きに届いて欲しい(笑)
疲れた時はどうぞ。猫見て癒されて下さい。

画像を表示しているのは、Webビューアですが、オブジェクトフィールドに格納してもらっても構わないです。
ちなみに[--FM-return-container-variable](https://help.claris.com/ja/pro-help/content/curl-options.html)ですぐに挿入可能です。


# サンプルいる？

15分前後で作ったので、あれこれは言わないで。
あと追加はご自身でお願い致します。いや、やりたいなら作り直しを。

[サンプルファイル](http://azurellama76.sakura.ne.jp/TheCatAPI.zip)

ちなみに犬版もあったから、気になる人はぜひそちらもやってみて！

今日も１日ありがとう！
3分でできる！Google 翻訳API

<p>alphavantage APIとか使って、以下のような株アプリを作ってる</p>

https://stonehills.tokyo/financer/
<!-- /wp:heading -->

<!-- wp:heading -->
<h2 class="wp-block-heading">1. APIコンソールを開く</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>APIコンソールを開いて、有効化されていることを確認</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><a href="https://console.cloud.google.com/apis/library?hl=ja">https://console.cloud.google.com/apis/library?hl=ja</a></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">2. サーバに資格認証の設定をする</h2>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">gcloud auth application-default login</pre>
<!-- /wp:preformatted -->

<!-- wp:heading -->
<h2 class="wp-block-heading">3. pip install</h2>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">$ pip install google-cloud-translate</pre>
<!-- /wp:preformatted -->

<!-- wp:heading -->
<h2 class="wp-block-heading">4. テストコードを作成</h2>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">
def translate_text(target: str, text: str) -> dict:
    """Translates text into the target language.

    Target must be an ISO 639-1 language code.
    See https://g.co/cloud/translate/v2/translate-reference#supported_languages
    """
    from google.cloud import translate_v2 as translate

    translate_client = translate.Client()

    if isinstance(text, bytes):
        text = text.decode("utf-8")

    # Text can also be a sequence of strings, in which case this method
    # will return a sequence of results for each text.
    result = translate_client.translate(text, target_language=target)

    print("Text: {}".format(result["input"]))
    print("Translation: {}".format(result["translatedText"]))
    print("Detected source language: {}".format(result["detectedSourceLanguage"]))

    return result

translate_text("ja","this is test")</pre>
<!-- /wp:preformatted -->

<!-- wp:heading -->
<h2 class="wp-block-heading">5. 翻訳実行！</h2>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">$ python3 gcloud_translate.py
Text: this is test
Translation: これはテストです
Detected source language: en</pre>
<!-- /wp:preformatted -->
Xcode15betaをGithub Actionsで配布する方法

Xcode15betaをGithub Actionsで配布する対応をご紹介します。

↓参考URL
https://github.com/marketplace/actions/setup-xcode-version

## ■作業手順
3箇所を15.0-beta用に変更する。
```yml
jobs:
  build:
    runs-on: macos-13　 1
    timeout-minutes: 60 
    steps:
    - uses: actions/checkout@v2
    - uses: maxim-lobanov/setup-xcode@v1　 2
      with: xcode-version: '15.0-beta'　 3
```

上記を導入したら、以下の部分はコメントアウトしました。
ちなみに最初はこの2箇所を変更して配布を試みましたが、バージョンがXcode15に変更されておらず配布は失敗しました。
```yml
#     - name: Select Xcode
#       run: sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
    - name: Xcode version
      run: /usr/bin/xcodebuild -version
    - name: Cache Pods
      uses: actions/cache@v2
      with:
        path: Pods
        key: ${{ runner.os }}-${{ hashFiles('**/Podfile.lock') }}
#        xcode-version: '15.0-beta'
```
URLをむやみに踏むべきではないのか

## はじめに
ネットサーフィン中に、URLからサイトに飛ぼうとしたり画像をダウンロードしようとするとインストールしている『富士通アドバイザー』から警告が来る

<img src="https://i.ibb.co/G97srNK/2023-08-24-141207.png" alt="2023-08-24-141207" border="0" />

画像の「このダウンロードは危険かもしれません」の原因を調査する
※筆者はサーバー・セキュリティの知識が皆無なので、かなり初歩的な調査になるかもです

## 思考の順番
1. 筆者の予想
1. 様々なサイトからの調査
1. まとめ


## 筆者の予想
**１．<font color="red">サーバーからクライアントへデータが返される時に一緒に害悪要素も返される説</font>**

サイトURLへ跳ぶ時の大まかな挙動は以下の通り
    １．HTTPリクエストをサーバーへ送信
    ２．サーバーは受け取ったリクエストに対し、適切なレスポンスを形成してブラウザへ送信
    ３．ブラウザは受信したレスポンスを解析し、Webページを表示する

上記の挙動でいう２に原因があり、**レスポンスを形成する中でウイルス等の害悪要素を仕込むプログラムが作られる可能性**が考えられる

**２．<font color="red">URLを踏んだアカウントを通じて情報が盗難される説</font>**
サーバー上でURLを踏んだアカウントの特定は多分可能なので、そこから**個人情報が抜かれる危険性**があると考える。

## 様々なサイトからの調査
**【引用元】**
・[画像ファイルにマルウエアが潜む](https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800013/101900058/)

・マルウェア入りの画像ファイルをネットからダウンロードさせることで、<font color="red">**マルウェアをPCに感染させることが可能**</font>
　・ただし画像ファイルを表示させただけでは感染はしない
**マルウェア**：悪いことを企んでいるプログラムのこと

▼マルウェア画像ファイルをダウンロードした時の挙動
<a href="https://imgbb.com/"><img src="https://i.ibb.co/D4Bdp1h/2023-08-24-161358.png" alt="2023-08-24-161358" border="0" /></a>

👆ファイルをダウンロードする際、そこにマルウェアスクリプトが含まれたら感染のリスクが高まるのか

<hr />

**【引用元】**
・[画像ファイルにウイルスが入ってる可能性ってある？](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10184391480)

<img src="https://i.ibb.co/h2py1x8/2023-08-24-162229.png" alt="2023-08-24-162229" border="0" />

<img src="https://i.ibb.co/nqpGCH0/2023-08-24-162236.png" alt="2023-08-24-162236" border="0" />

👆見た目はただの画像ファイルでも、それに偽装した悪質なプログラムを仕込むことは可能らしい。どうやってやって実現してるかは不明だが

<hr />

**【引用元】**
・[「ホームページにアクセスすると情報は取られるの？」](https://www.cman.jp/network/term/getinfo)

・<font color="red">**ある程度の情報は開設者に送信される**</font>
　・ただし個人を特定するような情報は送信されない
・**送信される情報**
　・**IPアドレス**：国・地域・使用回路のプロバイダーなどがわかる(個人は特定されない)
　・**OS・ブラウザ・使用機器情報**
　・**位置情報**：GPSを搭載したスマホやPCはほぼ正しい位置がわかる
　　　　　　　ただし、JavaSctiptで位置を取得とき通常は確認メッセージが表示され、
　　　　　　 <font color="red">**「許可」しないと位置は取得できない**</font>
　・**プラグイン**：ブラウザにインストールされているプログイン情報がわかる

👆思ったより色んな情報が分かってしまうらしい

<hr />

**【引用元】**
・[Q. サイトを見ただけで個人情報はわかってしまうのですか？](https://flets-w.com/chienetta/pc_mobile/cb_security06.html)

・<font color="red">**サイトを見ただけで個人情報がわかってしまうことは無い**</font>
　・ただし時間やOS、どの検索サイトから来たのかはわかる
　・**これは本来悪用目的ではなく、サイトの品質向上などへの情報収集の為に設けられている**

👆他のサイトでも個人情報が特定されることは無いと記述されており、この信憑性は高そう

## まとめ
**１．<font color="red">サーバーからクライアントへデータが返される時に一緒に害悪要素も返される説</font>**

👆正しい。
・悪意のあるスクリプトをウェブページに埋め込むことで、訪れたユーザーのブラウザで実行されるように仕掛けることが可能。
　・これによってPC上にウイルスやマルウェア侵入することが可能
　・これはファイルに埋め込むことも可能であり、これによりダウンロードを通じて仕掛けられる

**２．<font color="red">URLを踏んだアカウントを通じて情報が盗難される説</font>**

👆個人情報は盗まれない
・URLを踏んだだけだと、IPアドレスやOSなどの情報は開発者に送られるらしいが、個人情報を特定するものが送られることは無い
　・個人情報が送られるとすれば、ユーザーが自ら情報を開示した場合(フィッシングサイト等)に限る

## おわりに
極度にURLにアクセスることを不安がる必要はなさそう。
URLの安全性を出力してくれる無料サイトはたくさんあるので、何かしらインストールしていれば仮に害悪URLにアクセスしようとしても問題なく回避できる。
MacにてVSCode利用して、GitとGitHubを連携する方法

<h2>MacにてVSCode利用して、GitとGitHubを連携する方法</h2>
<h3>利用したサイトリスト</h3>
<a href="https://miya-system-works.com/blog/detail/vscode-github/">VSCodeでGit・GitHubを使う方法を解説する【初心者向き】</a>
<div>※大前提として、VSCodeを使用することが必須。</div>
<div>プロジェクトごとに連携が必要みたい。</div>
これ、収録してる？

　とあるゲームで、ゲームを収録している人には特殊演出が入る仕様があると聞きました。

　面白そうと思ったので、これの実装方法を考えてみました。メタ要素のあるゲームを作りたい方は参考にしてみて下さい。
　……あ、言い忘れていましたがC言語です。C++でももちろん動きます。あと、Windowsでしか動きません。

```c
#include <Windows.h>
#include <stdio.h>

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lp) {
	TCHAR window_text[1024];
	GetWindowText(hWnd, window_text, 1024);
	if (window_text[0] == L'O' && window_text[1] == L'B' && window_text[2] == L'S') {
		*(bool*)lp = true;
	}
	return TRUE;
}

int main(void) {
	bool is_obs = false;
	EnumWindows(EnumWindowsProc, (LPARAM)(&is_obs));
	if (is_obs) {
		printf("収録してる\n");
	}
}
```

　Windows APIの`EnumWindows`という関数を使っています。ウィンドウ名がOBSの三文字で始まる時、「収録してる」と表示されるプログラムです。
C#とVB.NETでWord文書にカスタムプロパティを設定する方法

## はじめに
文書のプロパティは、文書の特徴や属性を記述および識別するためのメタデータであり、通常、一般的なプロパティとカスタムプロパティに分類されます。この機能は、文書の管理と使用において重要な役割を果たします。一般的なプロパティに加えて、ユーザーは必要に応じてカスタムプロパティやタグを追加することもでき、文書の柔軟な管理と整理、作業効率の向上が可能です。以下では、Wordにカスタムプロパティを設定するためのプログラミング方法について説明します。

## ツール
* Visual Studio 2022 
* [Free Spire.Doc for .NET](https://www.e-iceblue.com/Introduce/free-doc-component.html)

## 準備
1. [Free Spire.Doc for .NET](https://www.e-iceblue.com/Download/download-word-for-net-free.html)をダウンロードします。
2. Visual Studioで新しいプロジェクトを作成します。
3. そのプロジェクトを開いた後、「Solution Explorer」>「References」>「Add Reference」>「Browse」を選択します。
4. BINフォルダ内のDLLファイルを見つけて、「OK」をクリックします。

上記の手順で DLL ファイルをプロジェクトに簡単にインポートできます。

## コード
**C#**:
```c#
using Spire.Doc;
using System;

namespace AddCustomDocumentProperties
{
    class Program
    {
        static void Main(string[] args)
        {
            //Documentインスタンスの作成
            Document document = new Document();

            //Word文書を読み込みます
            document.LoadFromFile("sample.docx");

            //カスタム文書プロパティを追加します
            CustomDocumentProperties customProperties = document.CustomDocumentProperties;
            customProperties.Add("ID", 1);
            customProperties.Add("Authorized", true);
            customProperties.Add("Authorized By", "小林");
            customProperties.Add("Authorized Date", DateTime.Today);

            //結果文書の保存
            document.SaveToFile("result.docx", FileFormat.Docx2013);
        }
    }
}
```
**VB.NET**:
```VB
Imports Spire.Doc
Imports System
Imports System.Reflection.Metadata

Namespace AddCustomDocumentProperties
    Class Program
        Shared Sub Main(ByVal args() As String)
            'Documentインスタンスの作成
            Dim document As Document = New Document()

            'Word文書を読み込みます
            document.LoadFromFile("sample.docx")

            'カスタム文書プロパティを追加します
            Dim customProperties As CustomDocumentProperties = document.CustomDocumentProperties
            customProperties.Add("ID", 1)
            customProperties.Add("Authorized ", True)
            customProperties.Add("Authorized By ", "小林")
            customProperties.Add("Authorized Date ", DateTime.Today)

            '結果文書の保存
            document.SaveToFile("Result.docx", FileFormat.Docx2013)
        End Sub
    End Class
End Namespace
```
上記のコードでは、まず`CustomDocumentProperties`という名前空間を定義し、その名前空間の下に`Program`というクラスを作成して、プログラムのエントリーポイントとします。`Main`関数では、まず`Document`オブジェクトを作成し、それはWord文書のインスタンスを表します。次に、`LoadFromFile`メソッドを呼び出してWord文書を読み込みます。そして、`CustomDocumentProperties`オブジェクトを取得し、`Add(string, object)`メソッドを使用してカスタムプロパティを文書のカスタムプロパティコレクションに追加します。
最後に、`SaveToFile`メソッドを呼び出して変更された文書を保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/7c1f9860-1395-a631-b15a-34be10aa5ac5.png)
【Drupal】DBデータをどうしてもSQLで取得したい場合

## 背景
項目追加等を行ったケースでプログラムがスパゲティ化しちゃうのでSQLで頑張ろうぜなシーンがあったので調べた

※使った事はないで仕様解析はしていませんがリビジョン設定がある場合、これで要件は満たせないと思われます。

## ユーザー情報

usersに持っている項目テーブルの一覧が出てくる

```SQL
show tables like 'user__field%';
```

代表的なフィールドを例にSELECT
※他にもあるけどそこは自分で解析してください
```sql
SELECT
	u.uid		-- drupal上のユーザーID
	,ufd.name	-- ユーザーのログインアカウント名
	,ufd.mail  	-- ユーザーのメールアドレス
	,ufd.init	-- ユーザー登録時のメールアドレスらしい
	,ufd.status	-- 0:block,1:active
	/* 
	,other.field_xxxx_target_id -- 他のEntityに紐づけている
	,other.field_xxxx_value -- 単独で値を持っている
    */ 
FROM
	users u 
INNER JOIN 
	users_field_data ufd 
	ON u.uid = ufd.uid
	AND u.langcode = ufd.langcode
[/*
LEFT JOIN
 	user__field_xxxxx as other
 	ON other.entity_id = u.uid
 	AND u.langcode = other.langcode
 	AND other.bundle = 'user'
*/
LIMIT 0,10;
```

## node
nodeに持っている項目テーブルの一覧が出てくる
```SQL
show tables like 'node__field%';
```

```SQL
SELECT
	n.nid	-- node id
	,ndf.created -- 作成日時の整数値 日付で見たい場合はcastして
	,ndf.changed -- 更新日時の整数値 日付で見たい場合はcastして
	/* 
	,other.field_xxxx_target_id -- 他のEntityに紐づけている
	,other.field_xxxx_value -- 単独で値を持っている
	*/
FROM
	node n
INNER JOIN
	node_field_data ndf
	on n.nid = ndf.nid
	AND n.type = ndf.type
	AND n.langcode = ndf.langcode
/*
LEFT JOIN
	node__field_xxxx other
	ON n.nid = other.entity_id
	AND n.type = other.bundle
	AND  n.langcode = other.langcode
*/	
WHERE
	n.type = 'xxxxx' -- 検索したいnode type
LIMIT 0,10;
;
```