OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】最小の差

# 実装概要
2つの整数配列 arrayOne と arrayTwo が与えられたときに、それらの配列間で最も差が小さい要素のペアを見つけるための関数。

# 実装
```python:smallest_difference.py
def smallestDifference(arrayOne, arrayTwo):
    # 与えられた2つの配列を昇順にソート
    arrayOne.sort()
    arrayTwo.sort()
    
    # 初期値を設定
    smallest, pair = float("inf"), []  # 最小の差と対応するペアを初期化
    oneIdx, twoIdx = 0, 0  # 配列のインデックスを初期化
    
    # 配列の要素を比較して最小の差と対応するペアを求める
    while oneIdx < len(arrayOne) and twoIdx < len(arrayTwo):
        numOne, numTwo = arrayOne[oneIdx], arrayTwo[twoIdx]
        current = abs(numOne - numTwo)  # 現在の差の絶対値を計算
        if current < smallest:
            smallest = current
            pair = [numOne, numTwo]  # 最小の差のペアを更新
        if numOne > numTwo:
            twoIdx += 1  # numOne > numTwo の場合、numTwoを次に進める
        else:
            oneIdx += 1  # numOne <= numTwo の場合、numOneを次に進める
    
    return pair  # 最小の差を持つペアを返す

# テスト
if __name__ == "__main__":
    arrayOne = [10, 0, 20, 25, 2000]
    arrayTwo = [1005, 1006, 1014, 1032, 1031]
    print(smallestDifference(arrayOne, arrayTwo))

```


# 参考
https://www.algoexpert.io
SwiftUI Textで文字列がnilな場合に表示する代替テキストを多言語化する

# 環境

Xcode 14.3.1

# Textの多言語化

SwiftUIのTextなどは文字列を与えることができます。

```swift
struct ContentView: View {
    var body: some View {
        Text("No Name")
            .font(.title)
            .fontWeight(.bold)
    }
}
```

この時、`No Name` という文字列に対してLocalizable.stringsで多言語化を行なっていると、多言語化された文字列が表示されることになります。日本語で `(名前なし)` と表示されています。

![スクリーンショット 2023-08-10 16.50.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687960/fc7087fe-4d74-b3f2-f5c3-2dafb347aba5.png)

# Textに与えられる文字列がnilの場合の代替テキストの多言語化

もし名前が与えられていたら名前を表示し、名前がない場合は、多言語化された名前がないことを示す代替テキストを表示しようと以下のようなViewを作成してみました。

```swift
struct ContentView: View {
    let name: String?
    var body: some View {
        Text(name ?? "No Name")
            .font(.title)
            .fontWeight(.bold)
    }
}
```


しかしこれは意図した通りには動きません。nameがnilの場合、`No Name` が表示されることになります。

![スクリーンショット 2023-08-10 16.51.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687960/5f7d24a1-eac8-8a25-ab5a-d47bf7e1f438.png)

これは、ただ単に固定の文字列が与えられている場合、Textは`LocalizedStringKey`と判断して多言語化を行いますが、今回はまずnameが与えられ、nameはStringのため、後に続く`"No Name"`もStringとして認識するからです。


```swift
struct ContentView: View {
    let name: String?
    var body: some View {
        if let name {
            Text(name)
                .font(.title)
                .fontWeight(.bold)
        } else {
            Text("No Name")
                .font(.title)
                .fontWeight(.bold)
        }
    }
}
```
上のようにnameのnilチェックを行なって分岐すれば多言語化されますが、後に続くViewModifierも丸ごと追記しないといけません。

# 結論

`Group` を使うことでStringがnilの場合の多言語化を行うことが可能です。 

```swift
struct ContentView: View {
    let name: String?
    var body: some View {
        Group {
            if let name {
                Text(name)
            } else {
                Text("No Name")
            }
        }
        .font(.title)
        .fontWeight(.bold)
    }
}
```

Groupを使い、中でnameの有無でTextの値をセットし、そしてGroupに対してViewModifierをつけることにより、共通的にTextにViewModifierを与えることが可能になりました。
【Rails】これを読めばマイグレーションファイルがわかる！

最近ruby on railsの学習を始めたのですがHTMLとPHPの勉強してきた人間なので、
はじめはマイグレーションという言葉の概念すらわからない状態でした。

なんとなくマイグレーションについてわかってきたので同じような初学者に向けて
学んだことをまとめていきたいと思います。

# 目次
[マイグレーションとは](#マイグレーションとは)
[マイグレーションを使うメリット](#マイグレーションを使うメリット)
[マイグレーションファイルを作成する](#マイグレーションファイルを作成する)
[マイグレートの実行](#マイグレートの実行)
[マイグレーションの修正](#マイグレーションの修正)
[絶対これはしちゃダメなこと
](#絶対これはしちゃダメなこと
)
# マイグレーションとは
そもそもマイグレーションファイルとは何か。
マイグレーションはデータベースの構造を書き記した設計書のようなものです。
データベースは以下DBとさせていただきます。
マイグレーションファイルのスゴイ所は、
SQL文を書かなくてもDBの変更（テーブルの作成や変更）ができるというところです。



# マイグレーションを使うメリット
##### DBの変更についてのログが残る
ファイルを作ってDBに変更を加えていくため、ログがファイルとして蓄積されていきます。
<img width="300" src="https://1.bp.blogspot.com/-v-UKcyhQ6Dw/VOsJhzAlK0I/AAAAAAAArpI/AD1q3yy-dmY/s800/syorui_yamadumi.png">
##### 同じファイルを持っている人間（例えばチームなど）がDBに同じテーブルを作成したいとき、それが容易になる
先程述べたように、マイグレーションファイルとはDBの構造の設計書のようなものです。
そのため、同じ設計書を持っていれば全く同じ構造のDBを作ることができます。
<img width="300" src="https://1.bp.blogspot.com/-tonUHy9fDEk/XnLn7EL4lvI/AAAAAAABX0k/HvgZidpGmQc7-Qe7LDsp00TfWltpuwkSwCNcBGAsYHQ/s1600/computer_mob_programming.png">

# マイグレーションファイルを作成する
マイグレーションファイルを作成したいときには以下のコマンドで作成することができます。<br>
`rails g migration ファイル名　カラム名:データ型`
カラム名とデータ型についてはファイルを作った後にファイル内で編集することもできるため、なくても大丈夫です。データ型などのファイル内での記述については今後の記事で書いていきたいと思っているため本記事では割愛させていただきます。

このコマンドを実行するとマイグレーションファイルとテストファイルが作成されます。
マイグレーションファイルは**db/migrate/作成した日付_ファイル名.rb**に作成されます。
また、rails gにはmigration以外にも種類があります。
migration以外のコマンドで作成できるものについては 以下のサイトが参考になります。

https://qiita.com/kodai_0122/items/14494a3848654f32909d

# マイグレートの実行
マイグレーションに記述した内容をDBに適用することをマイグレートと呼びます。
マイグレート時のコマンドは以下になります。
`rails db:migrate`

このコマンドを実行するとdb/migrate/に含まれているファイルが古い順に読み込み・実行されます。

# マイグレーションの修正方法
「あ、カラム名ミスった、、、」っていうことが発生した時はどうしましょう（優秀な方ならなさそうですが…）。
<img width="300" src="https://4.bp.blogspot.com/-iLWX4m_Pht8/XDXcK2opNnI/AAAAAAABRHg/KkSa_pjFcygNx7-v-5AC12TFp08xNXlIgCLcBGAs/s800/sick_panic_man.png">
まずは、ファイルの状態を確認します。
`rails db:migrate:status`

**up**はmigrateで反映済み、**down**は反映がされていない状態です。

##### 新たにファイルを作成する
修正のためのファイルを作成し、その中に修正内容を記載します。
例えば、作ったカラムの名前を間違えていた時はそのカラムを削除し、
新たに正しい名前のカラムを追加するといったような修正方法です。

##### マイグレーションの変更をもとに戻す
`rails db:rollback`で1つ前に戻すことができます。
そして変更をしたいファイルを**down**の状態にした上で変更し、
再び`rails db:migrate`をします。


# 絶対これはしちゃダメなこと
やってはいけないこと。それは、、、
##### マイグレートファイルの内容を書きかえることです。
なぜかというと、書きかえると環境ごとで辻褄が合わず、
**統合がとれない、エラーが発生するなどの問題が生じる**可能性があります。
また、メリットとしてログが残ることを挙げましたが、書きかえてしまうと書きかえたというログは残らないため完全なログが残せなくなります。

### 参考

https://railstutorial.jp/

https://zenn.dev/yuuuuu/articles/90402a00161727
セキュリティ資格の勉強でよく遭遇する誤訳や概念

# はじめに
セキュリティの資格試験（特に国際資格）の勉強をしているときに、私が遭遇した誤訳や概念についてまとめることにした。

# この記事の想定読者
特になし

# 本題
**データカストディアン、データオーナ**
最近は割りと見なくなった気がするが、データオーナのことをデータ管理者と訳してある文献をたまにみるが、これはややこしいのでやめてほしい。データ管理者は一般にデータカストディアンのことを指す。データオーナはデータ所有者と直訳してほしい。。


**Blowfish、ふぐ**
暗号アルゴリズムでBlowfishというアルゴリズムが存在するのだが、これを日本語に訳する「ふぐ」となる。
問題集をGoogle翻訳なんかで翻訳して演習していると、たまに以下のような感じになる。

```
XXXで使用する主な暗号アルゴリズムは？
1. RSA
2. ECC
3. ふぐ
```

ここで「ふぐ」って何だ？と思うのだが、この場合、「ふぐ＝Blowfish」と脳内変換する必要がある。

**Authentication、Authorization、Certification**

上記３つはすべて認証と訳されることがあるが、これは誤訳。

```
次のうち、XXXはどれか？

1. Authentication
2. Authorization
3. Certification
```

**DES、データ暗号化基準**
DES＝Data Encryption Standard　なので、これを直訳すると「データ暗号化基準」なのだが、このままだと以下のような問題では大変違和感を感じる。

```
データ暗号化基準の特徴はなにか？

1. XXX
2. YYY
3. ZZZ
```

そもそも「データ暗号化基準」って何って話になるのだが、「データ暗号化基準=DES」だと見抜けないと、この問題は無理。。

**最も野蛮な方法**

これは今でもよくわかっていないのだが、「野蛮な方法＝悪用しやすい」という意味なのか。もしくは人間的な方法という意味なのか。

```
次のうち、最も野蛮な攻撃方法はどれか？

1. DDoS
2. 拷問
3. 脆弱性を突いた攻撃
```

書いている自分もよくわからなくなってきた。。

# 最後に
米国などの独特の概念に加えて、誤訳対策も試験対策の一貫として実施すると良いと思いました。
思い出したら、また追記していきます。
vim から Github Copilot を使ってみた（プロキシ経由）

[プラグインのリポジトリ](https://github.com/github/copilot.vim)の手順に沿っていれば問題ないと思いますが、[vim-plug](https://github.com/junegunn/vim-plug) を使っているので vim-plug からインストールしてみました。
社内プロキシ用の設定もします。

## 前提事項

vim, vim-plug, node.js のインストール

私は wsl と asdf を使っていますが、vim-plug が使えている状態であれば github の認証手順がちょっと変わるくらいで、他は変わらないと思います。

## vimrc の編集

プラグインマネージャとして vim-plug を使っている場合の手順です。
私は他のマネージャ（deinとか？）は使ったことがないので、そちらは分かりません。

.vimrc を開いて、vim-plug の設定に以下を追記します。

```vim
call plug#begin()
" ↓を追記
Plug 'github/copilot.vim'
call plug#end()
```

プロキシを使っている場合は copilot 用のプロキシ設定を追記します。

```vim
let g:copilot_proxy = '<プロキシサーバのURL>:<ポート番号>'
```

## インストール

vim を開き直して（.vimrc をリロードして）下記コマンドを実行します。

```vim
:PlugInstall
```

## セットアップ

```vim
:Copilot setup
```

でセットアップを開始。私の環境では vim に表示されたパスコードをブラウザで入力すれば認証されました。
環境次第で github へのログイン等をする必要があるかもしれませんが、表示される指示の通りに操作すれば問題ないでしょう。

## 使ってみる

有効化されているかを確認するには、次のコマンドを打ちます。

```vim
:Copilot status
```

.vimrc で試してみると `Copilot: Enabled and online` になっていました。
python 用のファイルタイプ設定を出したりしてくれました。.vim ファイルでもサジェストしてくれます。

インサートモードで改行したりちょっと待ったりするとサジェストが出てきて、tab でサジェストを採用できます。

yaml ファイルでも使おうと思ってステータスを見たところ、 `Copilot: Disabled for filetype=yaml by internal default` と出てきました。デフォルトでオフになっていますね。

バッファに対してCopilot の使用を強制するには、

```vim
:let b:copilot_enabled=v:true
```
 
を打ちます。
yaml で有効化して試したところ、いい感じにサジェストされました。

あらゆるファイルでとりあえず有効にしたい場合は、

```vim
let g:copilot_filetypes = {
    \ '*': v:true,
    \ }
```

を .vimrc に追記すれば良さそうです。
ファイルタイプごとのオンオフもグローバルに設定できるようになっています。

## おわりに

ヘルプコマンドで Copilot プラグインの説明が見れます。

```vim
:help Copilot
```

スペースがアンダースコア（_）で書かれている場合があるので注意。

思ったよりプラグインの設定項目は少なく、眺めていたらプロキシ設定が見つかりました。
Wordpress6の新規ユーザーを追加ができない問題の対策方法

## 概要

Wordpressの新規ユーザーを追加画面で必須項目を入力し、「新規ユーザーを追加」ボタンをクリックすると、`パスワードが一致しません。両方のパスワード欄に同じパスワードを入力してください。`とエラー文が表示され登録できない。

![wordpress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329178/9da3f8ba-03cd-6be4-206a-dac35ff98d45.png)

## 対策
調査した結果、パスワードの項目の下にある`パスワードを再入力`の項目がJSによって隠されていることを発見した。
よってこれを開発者ツールで消す(`hide-if-js`)

### 削除前
![wordpress2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329178/14587088-c15e-fa27-2fc0-eff637de1f76.png)

### 削除後

![wordpress3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329178/3ae0ab61-8f4c-e3eb-6f6a-6e8748eabe2b.png)

### WPの表示
現れました。
これで登録することができました。
![wordpress4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329178/f97d8a8a-22b6-9b1c-137f-36bfd7269441.png)

## 参考

 - Youtubeでの説明
https://www.youtube.com/watch?v=YarAvxOFjWg
新卒エンジニアがGitを使いこなすための基本的なコマンド集


新卒エンジニアがGitを使いこなすために最低限必要なコマンドをまとめてみました。



 ## add
```$ git add [変更を加えたファイル]  ```
addをすることで該当ファイルを作業領域からステージング領域に登録することができます。

よくある使いかた
```$ git add .  ```
カレントディレクトリ以下の変更を加えたファイルをすべてをadd することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587277/d3a58a86-4f40-f91c-8538-42f0abf32487.png)


公式ドキュメント
https://git-scm.com/docs/git-add/ja

 ## commit 
```$ git commit  ```
ステージング領域に追加されたファイルをコミットし、ローカルリポジトリへ登録します。

よくある使いかた
```$ git commit  -m "[message]"```
コミットにメッセージを付けることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587277/0edf0f0a-3a40-9ff4-acaf-e9ab071f53a9.png)

公式ドキュメント
https://git-scm.com/docs/git-commit


 ## push
```$ git push  [remote] [branch]```
ローカルリポジトリで追加されたコミットをリモートリポジトリへ登録することができます。

使用例
```$ git push origin [作成したリポジトリのURL]```
```$ git push origin [ブランチ名]```

※補足
originがどこのリモートリポジトリと紐づいているのかを確かめる方法として
```$ git remote -v ```
を実行し、確かめるとよいでしょう。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587277/7cd1e382-7ce9-cbef-6359-55863ce7a636.png)

日本語版ドキュメント
https://tracpath.com/docs/git-push/


 ## reset
```$ git reset ```
Gitでコミットした内容を取り消したり、ファイルの状態を巻き戻したりするコマンド。

主なオプション
```$ git reset --soft```

使用例
```$ git reset --soft HEAD^```
直前のコミットまで巻き戻す場合

※HEAD^とは
「１つ前のコミット」という意味
HEAD^^だと「２つ前のコミット」となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587277/13efec6b-4c88-d1c3-8a3d-91d9ba624b29.png)

```$ git reset --mixed```
commitとaddを巻き戻す。

使用例
```$ git reset --mixed HEAD```
addでステージしたものを取り消したい時などに使用できます。
作業領域での変更点は消えません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587277/39b58995-66b5-40b0-f90d-be23351a681b.png)

```$ git reset --hard```
ローカルリポジトリでコミットした内容をすべて戻す。

使用例
```$ git reset --hard HEAD^```
ひとつ前のコミットまで丸ご戻す場合。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587277/d99afa08-0808-69e6-9449-9cebebeee6a3.png)





日本語版ドキュメント
https://tracpath.com/docs/git-reset/
 ## diff
```$ git diff```
作業領域とステージング領域との差異を表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587277/0ed8bc0e-71ef-01e1-12ee-13b05eba05dc.png)

公式ドキュメント
https://git-scm.com/docs/git-diff

 ## log
```$ git log```
変更履歴を見たいとき


```$ git log　--oneline```
一行ずつ見たいとき。
``` 
283116d commitA
a9f9fe4 commitB
1bd5777 commitC
2d924e6 commitD
```



日本語版ドキュメント
https://tracpath.com/docs/git-log/
 ## status
```$ git status```
作業領域の状態とステージング領域の状態を表示するコマンド。
どこの変更がステージング済み（addしてある）かそうでないかを表示することができます。

日本語版ドキュメント
https://tracpath.com/docs/git-status/


 ## checkout
```$ git checkout  ```
ブランチの切り替えやファイルの復元の２つの機能を持ちますが、
今回はブランチの切り替えについて紹介していきます。

```$ git checkout baranchA ```
branchAに移動することができます。

オプション```-b```
```$ git checkout -b branchB```
新しくbranchBを作成し、branchBへ移動します。

日本語版ドキュメント
https://tracpath.com/docs/

 ## pull
```$ git pull```
リモートリポジトリにある内容を現在のブランチに反映させるコマンド。

使用例
```$ git pull origin [branch name]```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587277/0823e1ba-6ce0-70a6-646f-f215a7113205.png)

日本語版ドキュメント
https://tracpath.com/docs/git-pull/

## 参考文献
https://qiita.com/2m1tsu3/items/6d49374230afab251337
自分用備忘録：複数tsvを1エクセルにまとめる

自分用備忘録

    def sum_excel():
        """
            フォルダごとに複数tsvを1つのexcelでまとめて出力
        """
        output_list = glob.glob(f"output1/*", recursive=True)
        for isp_path in output_list:
            isp = os.path.basename(os.path.dirname(isp_path))
            tsv_list = glob.glob(f"output1/{isp}/*.tsv", recursive=True)
            data = {}
            for tsv in tsv_list:
                df = pd.read_csv(tsv, dtype='string', sep='\t')
                data.setdefault(isp, df)
            # 1つのexcelに1シートごとに出力
            with pd.ExcelWriter(f'output1/total_{isp}.xlsx') as w:
                for df in data:
                    print(df)
                    data[df].to_excel(w, sheet_name=f"{df}")
"""
スッキリわかるJava入門 第３版を読んでみて- part９ -さまざまなクラス機構

# はじめに
こんにちは(・ω・）ﾉ
今回はコンストラクタについて学びました！
## 第９章　さまざまなクラス機構
### 1.クラス型と参照
今までのイメージ...仮想世界
↓
実際は...「コンピュータのメモリ領域」

ヒープ...JVMが大量にメモリ領域を使って準備するもの

インスタンスとは、「ヒープの中に確保されたメモリ領域」


##### インスタンスが生まれる時のコンピュータの動き
以下のコードを参考:point_down:
```
public class Main{
    public static void main (String[] args){
        Hero h;
        h = new Hero();
        h.hp = 100;
    }
}
```

##### Step1.Hero型変数の確保
最初に動くのが３行目の「Hero.h;」
⇨「Hero型の変数h」をメモリ内に準備する
Hero型のインスタンスだけが入れることのできる箱が準備される

##### Step2.Heroインスタンスの生成
４行目「h = new Hero();」の代入文を実行する
代入は右辺が先に評価される
「new Hero()」でJVMがヒープ領域から必要なメモリを確保する
仮に3922番地から3945番地を確保できたとする

ここで仮想世界に存在が生まれたが属性はない状態

##### Step3.参照の代入
右辺の実行後の４行目...「h = 右辺の実行結果」
hには何が入るか?
❌勇者のインスタンス
⭕️newによって生成されるインスタンスのために確保された先頭番地
変数hには3922という数値が代入される

変数hに入っているアドレス情報...__参照__

配列型とクラス型の総称...__参照型__

##### Step4.フィールドへの値の代入
5行目「h.hp = 100;」の実行
JVMの解釈と動き
1.変数hの内容を調べて「3922番地を参照」と書いてある
2.3922番地のインスタンスのメモリ領域へアクセス、その中のhpフィールドを書き換える

変数から番地情報を取り出し、次にその番地にアクセスする
　⇨参照の解決やアドレス解決

同じクラスから生まれた異なるインスタンス
　お互いに影響を受けない...インスタンスの独立性

あるクラスが別のクラスをフィールドとして利用している関係...has-aの関係

String型は実は「クラス型」
　APIとして標準添付されている
Java.langパッケージで宣言されている
””で文字を囲めばインスタンスを生成して利用できる

### 2.コンストラクタ
newで生まれたインスタンスには初期値しかない
フィールドの初期値
int型などの数値の型...0
char型（文字）...¥u0000
boolean型...false
int[]型などの配列型...null
String型などのクラス型...null

newされた直後に自動的に実行されるメソッド...__コンストラクタ__

:sparkles: コンストラクタは直接呼び出せない
　コンストラクタはインスタンスの生成時にJVMによって呼び出されるものであり、
　開発者がプログラムで直接呼び出す手段は用意されていない

:notebook:コンストラクタとみなされる条件
1.メソッド名がクラス名と完全に等しい
2.メソッド宣言に戻り値が記述されていない（voidもダメ）

:pencil2:コンストラクタの定義
```
public class クラス名　{
    クラス名(){
        自動的に実行する処理
    }
}
```

コンストラクタに情報を渡す
　渡すべき引数をnewするときに指定する

:sparkles: 複数のコンストラクタが適宜されていた場合
　newするときに渡した引数の型・数：・順番に一致するコンストラクタが動作する
　（動作するコンストラクタは１つのみ）

:warning:すべてのクラスはインスタンス化で必ず何らかのコンストラクタを実行する
　　本来すべてのクラスは最低でも１つ以上のコンストラクタが必要

:sparkles: コンストラクタの特例
クラスに１つもコンストラクタが定義されていない場合のみ
　「引数なし、処理内容なし」のコンストラクタ（デフォルトコンストラクタ）
がコンパイル時に自動的に追加される

:pencil2: 同一クラス内の別コンストラクタの呼び出しをJVMに依頼する
```
this(引数);
```

## まとめに
イメージとして仮想世界で今まで話をしていたけど、実際はコンピュータのメモリ領域
クラス型変数にはインスタンスの情報が格納されているメモリの先頭番地が入っている
⇨別の変数に代入すると、番地情報がコピーされる
コンストラクタはnewによってインスタンス化の直後に自動的に実行されている
かなり難しい内容だなと読んでいて思いました。
クラス型の参照は配列の時と同様に代入で勘違いしてしまうと思うので、アドレスを参照していることをしっかり覚えておきたいです
コンストラクタは読んで何となくわかった...って感じなので繰り返し復習が必要だと感じました

今回もありがとうございました！
ではまた〜　＊˙︶˙＊)ﾉ"
MariaDBをマルチインスタンスで起動する（ubuntu20.04環境）

***必要な手順***
- データディレクトリを分ける
- 設定ファイルを分ける（ポート・データディレクトリ・ソケットファイル・PIDファイル・エラーログの出力先これらの指定をする）
- ソケットファイルおよびPIDファイル、エラーログの出力先を別々に指定する




---

dBに接続する際は注意が必要です。
何も指定せずにコマンドを実行するとデフォルト設定の3306ポートを利用した設定を見に行くようになっています。
それ以外のインスタンスを見に行く際はソケットファイルを指定することでそのファイルを利用しているインスタンスへ接続することが可能になります。
```
mysql -S {ソケットファイルのパス} -u {作成したユーザー名} -p
```

galera_clusterを利用することも可能です。
galera_clusterをマルチ稼働させることも可能です。


起動方法は通常と同じくsystemctlを利用します。
`systemctl start mariadb@{設定ファイル名}.service`




---
本記事は、執筆時点での知識と経験に基づくものです。情報の正確性や有用性について保証するものではありません。
参考にする際は、自己の判断と責任でお願いいたします。
after_sign_in_path_for(resource) の resourceってなに？

# ChatGPTに聞いてみた
https://chat.openai.com/share/4db98f35-90e3-4c96-a0a2-44d1a1477fa2

質問文：
> def after_sign_in_path_for(resource)
    about_path
  end<br>
上記のコードでメソッドの引数に"resource"を渡しているけど、このresourceって何？


回答：
> 提供されたコードは、Deviseと呼ばれるRails用の認証ライブラリで一般的に使用されるものです。このコードは、ユーザーがサインイン（ログイン）した後にリダイレクトする先のパスを指定するためのメソッドです。<br>
***after_sign_in_path_for メソッドは、Deviseが提供するコントローラー内で使用され、サインインが成功した後にユーザーをリダイレクトする先のパスを決定します。メソッドの引数 resource は、Deviseがサインインに使用するリソース（通常はユーザーモデル）を指します。この引数を使用して、サインイン後のリダイレクト先を動的に設定することができます。***<br>
具体的には、about_path はサインイン後にリダイレクトする先のパスとして指定されています。これはアプリケーション内で定義された about_path ヘルパーメソッドによって生成されるパスを示しています。<br>
したがって、このコードは、ユーザーがサインインした後に「about」ページにリダイレクトされるように設定されていると解釈できます。

つまり、Deviseがサインインに使用するユーザモデルのことやね。これ使えば、ユーザidに依存するページ（例えば、users#showとか）を指定できるってことやね。
逆に、引数でresourceを指定したけど、実際にユーザIDに依存しないページにリダイレクトさせたいときは使わなかったらいいんだね。

さすがChatGPT、わかりやすい。
canvasで画像をクリッピング

画像をドーナツの形に切り取る。

```javascript
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');

const img = new Image();
img.src = './img/test.jpg';

img.onload = function(){
	context.drawImage(img, 0, 0, 200, 200);
    	context.globalCompositeOperation = "destination-atop";
		context.beginPath();
		context.lineWidth = 30;//線の太さ
		context.arc(100, 100, 80, 0, Math.PI*2, true);
		context.stroke();
		context.closePath();
	}
```



   
　　　
　　　　　　

画像を乗算で重ねる

```javascript
async function loadImages(urls){
    let images = [];
	let promises = [];
	urls.forEach((url) => {
    	const promise = new Promise((resolve) => {
        	const img = new Image();
    		img.src = url;
    		img.onload = function(){
    			resolve();
    		}
    		images.push(img)
    	});
    	promises.push(promise);
    });
    await Promise.all(promises);
    return images;
};

async function drawImage(){
    const images = await loadImages([path, path2]);
	context.drawImage(images[0], 0, 0, 200, 200);
	context.globalCompositeOperation = 'multiply';
	context.drawImage(images[1], 0, 0, 200, 200);
}

drawImage();
```

----------------------
参考


https://qiita.com/fujimu/items/8930423835e519dab50d



https://qiita.com/yamazaki3104/items/abbcb88f573d3c5a4a40



https://pisuke-code.com/js-load-image-synchronously/
VSCodeでJupyter対話環境を速攻で作る

## これは何の記事？
Google colabで巨大なデータを扱おうとすると、RAM容量オーバーでクラッシュする事態が発生
VScodeに切り替えることに

流れを簡単に記載するので誰かの参考になれば

## 環境
VScode

## 記事の流れ
 - 環境構築の流れ
 - ローカルcsvファイルを読み込む 
 - 補足（Google colab）


## 環境構築までの流れ
#### 1. VSCodeをインストール
https://code.visualstudio.com/download
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/c9fa56c3-a36e-0d43-36ca-7a9e76634d51.png)

#### 2. ターミナル ⇒ 新しいターミナルを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/4d337759-77ec-8bb6-b9eb-db383b59041e.png)

#### 3. 仮想環境
ターミナルに「python3 -m venv .venv」と入れて実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/57049705-88c2-1e4b-b147-fc2de02619f9.png)

#### 4. Jupiterパッケージをインストール
ターミナルに「pip install jupyter」と入れて実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/6f32fc0b-47d4-369b-0939-5d5b77e15e32.png)

※もしpipコマンドをインストールできていない場合、以下からインストール
https://pypi.org/project/ipykernel/

#### 5. 新しいファイルを開く
ファイル ⇒ 新しいファイルからJupiter Notebookを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/f6522665-a9b7-1c7a-9b53-cc7bc9d0f0c2.png)

#### 6. カーネルの選択
Pythonを選択、これで環境構築完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/062cad34-f78f-f267-6f36-08d5aab845f4.png)


## ローカルファイルを読み込むまでの流れ
#### 1. 必要なモジュールを読み込む
「pip install pandas」で実行
他にも、numpy や matplotlib など必要なものをすべて入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/d7d68306-165c-ad57-3629-438a22184f19.png)

#### 2. cdメソッドで読み込みファイルの位置を指定
「cd C: (ディレクトリ　※ファイルの位置)」を入れ実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/ffe036c1-a0ae-3f61-f36c-bfa682a83769.png)

要はフォルダのこの部分をコピペ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/d9ee1bd5-0c02-4148-d1a0-aef2c0e18e34.png)

※試しにpwdメソッドを実行すると、現在位置が先ほど指定したディレクトリになっている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/bd73438b-9086-9a11-cfc5-97dae7c13007.png)

#### 3. 訓練データを読み込む
read_csv("ファイル名")で読み込める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/f51ac4f6-37b7-bc04-3d06-495038889285.png)

## 補足
もし容量的にGoogle colabで間に合うなら、無理してVSCodeでしなくてもよいかも。例：Titanic分析

その際、環境構築（csv読み込ませまで）は以下参照
https://qiita.com/kame_house_0828/items/aa68ea187cf5c02b6b36
Salesforceのアンケートのライセンス

[Salesforceのアンケートに戻る](https://qiita.com/Keiji_otsubo/items/ce153ec9d338d7af0d81)

+ [フィードバック管理ライセンス:各ライセンスのサポートされている機能の比較](https://help.salesforce.com/s/articleView?id=sf.concept_add_on_license.htm&type=5)

Salesforce Feedback Management は次のライセンスで使用できます。

+ Survey Response Pack
+ Feedback Management - Starter
+ Feedback Management - Growth

---------------------

+ [アンケート - Salesforce フィードバック管理ライセンス](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000074pyv9SAA)

:::note
Note every org as a one-off gets 300 free surveys. if you continue to use then you will at some stage be billed - but you aren't stopped from using them. The one-off is over the org lifetime not annual. It will at least allow you to try it out and determine whether it's a feature you would like to use, then you can plan your implementation and pre-purchase survey packs from Salesforce. It's much cheaper to pre-purchase packs than to simply overrun and pay the overage (they will eventually catch up with you!).

Also worth noting is that the count of survey consumption is on COMPLETED surveys - not the number you send out. Depending on the survey, of course, my experience is that it's a typically fairly low percentage that get completed. (Fun Fact: in Aotearoa NZ we used Salesforce surveys extensively for the Covid response!).

すべての組織が 1 回限りで 300 件の無料アンケートを取得できることに注意してください。使用を続けると、ある段階で料金が請求されますが、使用が停止されるわけではありません。1 回限りの場合は、毎年ではなく、組織の存続期間全体にわたって行われます。これにより、少なくとも試してみて、使用したい機能かどうかを判断し、実装を計画し、Salesforce からアンケート パックを事前購入することができます。単に超過して超過料金を支払うよりも、パックを事前購入した方がはるかに安価です (最終的には追いつきます!)。

また、アンケートの消費数は送信した数ではなく、完了したアンケートに基づいていることにも注目してください。もちろん、アンケートによって異なりますが、私の経験では、アンケートに回答できる割合は通常かなり低いです。(興味深い事実: ニュージーランドのアオテアロアでは、Covid 対応のために Salesforce アンケートを広範囲に使用しました!)。
:::

+ [Salesforce アンケートの差し込みフィールドが設定できない](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007CGNPL)

:::note
Salesforce Feedback Management is available with these licenses.

+ Survey Response Pack
+ Feedback Management - Starter
+ Feedback Management - Growth

https://help.salesforce.com/s/articleView?id=sf.concept_add_on_license.htm&type=5

https://www.salesforce.com/editions-pricing/platform/feedback-management/
:::

+ [フィードバック管理エディションを使用していないため、Salesforce Health クラウド標準調査エディションのマトリックス質問タイプの代替を探しています。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007F4XyQ)

ないみたい
StreamlitをDatabricks Cluster上で動かす

以前はダメだったと思うのですが、最近のstreamlitのバージョンだとDatabricksのcluster上で動かせるようなので、Driver Proxyを使ってアクセスする手順をまとめてみました。

ちなみにDatabricks Runtimeは13.1、streamlitのバージョンは1.25.0で確認しています。

:::note warn
ChainlitやGradioは動作しませんでした。
Driver ProxyのURLを経由すると、外部ファイルに対するパスが正しく設定されないようです。
base_urlのようなパラメータを設定できれば使えると思うのですが、未調査です。
:::


# 手順

## streamlit用のpyファイルを作成

まず、streamlitで表示するpyファイルをDatabricks上で作成します。
今回はReposを使わず、ワークスペース内にmy_streamlit.pyとしてファイルを作成します。

``` python:my_streamlit.py
import streamlit as st

st.set_page_config(
    page_title="streamlit driver proxyサンプル",
    page_icon="📝",
)

st.title("Streamlit driver proxyサンプル")
```

## streamlit起動用のノートブックを作成

次に、Stremlitを起動するためのNotebookを作成します。

最初のセルでstreamlitをinstall。

```
%pip install streamlit
```

次のセルで、Driver ProxyのURLを取得するための処理を記述。
これを実行して表示されるURLを、最終的にブラウザで開きます。

```python
from dbruntime.databricks_repl_context import get_context

def front_url(port):
    """
    フロントエンドを実行するための URL を返す

    Returns
    -------
    proxy_url : str
        フロントエンドのURL
    """
    ctx = get_context()
    proxy_url = f"https://{ctx.browserHostName}/driver-proxy/o/{ctx.workspaceId}/{ctx.clusterId}/{port}/"

    return proxy_url

PORT = 1501

# Driver ProxyのURLを表示
print(front_url(PORT))

# 利便性のためにリンクをHTML表示
displayHTML(f"<a href='{front_url(PORT)}' target='_blank' rel='noopener noreferrer'>別ウインドウで開く</a>")
```

front_url関数内で、Driver Proxyの接続先URLを生成しています。
URLは以下のルールになっているようで、そのルールに則ってURLの文字列を生成しています。

``` https://{ワークスペースのホスト名}/driver-proxy/o/{ワークスペースID}/{クラスタID}/{ポート番号}/ ```

なお、```driver-proxy```の部分を```driver-proxy-api```に変更すると、アクセストークンを利用して接続するAPIサーバ用のURLになります。


次のセルで、streamlitを起動する処理を記述。
streamlit_fileにはmy_streamlit.pyのパスを指定してください。

``` python
streamlit_file = "/Workspace/XXXXXXX/my_streamlit.py"

!streamlit run {streamlit_file} --server.port {PORT}
```

Notebookの処理を全て実行すると、URLが表示された上で、streamlitが起動します。

:::note warn
最後のセルを実行すると、Notebookが処理中状態のままになります。
クラスタの自動終了が機能しなくなるので、停止することを忘れないようにしてください。
:::

## ブラウザからstreamlitのUIを開く

二つ目のセルに表示されるURLをブラウザで開くと、stremlitの画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168727/66c94865-1d0e-f55c-ed43-f2b8d0dae4bc.png)


# 補足1

streamlitの開発においては、streamlitを停止させずにUI定義ファイル(my_streamlit.py)を更新して、ブラウザ側でRerunさせるのが普通だと思います。
一方、Workspace内のmy_streamlit.pyを変更しても（ファイルシステムが特殊なせいか）、Rerunで即座に変更が反映されません。

いい方法かわからないのですが、開発中はstreamlitを起動する際に直接Workspace内のファイルを指定せず、一度pyファイルをクラスタのローカルストレージにコピーし、コピー後のファイルを使って起動するようにしています。
my_streamlit.pyを更新した後は、再度ローカルにコピーして上書きする処理を実行し、Rerunすると画面が最新化されます。

# 補足2

クラスタ上で動かせるので、そのままstreamlit内でSparkも簡単に使えるんじゃないかと思ったのですが、これはうまくいっていません。sparkSessionの取得・作成がうまくできず。
有識者の方、どうすればいいのか教えてください。
（UI側にSpark処理を書くことの是非はありますが）

# まとめ

**Enjoy your Databricks life!!**
MVVMのModelとは何か

# MVVMのModelとは

ソフトウェアのUIに関わらない部分

ModelはUIについて知らない。
ModelはUIを意識しない。
ModelはUIの存在を関知しない。
UIに関わらないので、UIのデータは持たない。
UIに関わらないので、UIのロジック（プレゼンテーションロジック）は持たない。

UIから依存しないで独立しているので、UIの変更に影響されない。
MVVMのViewModelとは何なのか

MVVMのViewModelが何ものなのかわからない人へ

ViewModelは「ViewのためのModel」です。
Modelとはデータとロジックの事です。


# ViewModelの責務

１．Viewに表示するデータ(Viewの状態）の保持
　　（双方向バインドの場合は入力データの保持）
２．Viewの入力の受付
３．Modelとのやり取り

この３つの責務を処理するプログラムがプレゼンテーションロジック

ViewModelはViewの状態とプレゼンテーションロジックを持つ。


# ViewModelの役割

　ViewにUIの状態とロジックを入れない。
　ModelにUIの状態とロジックを入れない。


# ViewModelの誤解

・ViewModelはViewの抽象化したものである。

　Viewに対してViewの表示データを保持するのがViewModel
  　抽象化とは関係ない。

・ViewModelはViewのモデリングしたものである。

　viewに対してViewの表示データを保持するのがViewModel
　Viewをモデリングしたものではない。

・ViewModelはViewとModelの橋渡しである。

　橋渡しは役割の一部。橋渡しだけではない。

・ViewModelはViewの都合によりある

　ViewModelはViewからデータと入力処理とUIロジックを
　出すというMVVMの都合によりある。

・ViewModelがバインドを実行している
・ViewModelはバインドのためにある。

　バインドはV-VM間の実装方法を一例であり
バインドとViewModelは関係はない。

・Viewが消えるのでデータを保持するためにViewModelがある。

　ただの偶然。これはViewModelの目的ではない。
数式でうるう年を扱う


+ [2つの日付の間のうるう年で増えた日数をカウントする](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007AjNTF)

```
MOD(DATE(YEAR(End_Date__c),1,1) - DATE(YEAR(Start_Date__c),1,1),365)
```
docker-composeで動かしているGrowiの移行手段

## Gwori移行手順
docker-composeで動作している前提です。

### 動作確認環境
* 旧サーバー: Windows10 on Virtualbox on Ubuntu 20.04
* 新サーバー: Windows10 on WSL2 on Ubuntu 22.04
* Growi(新旧共通): v5.0.3
* 新サーバーdocker-compose: v1.29.2
* 新サーバーdocker: v20.10.21


### 古いサーバー上での操作

```shell-session
$ docker-compose stop
$ tar -czvf growi_volumes.tar.gz $(find /var/lib/docker/volumes -name 'growi*')
```

できあがったtar.gzを新しいサーバーへ移動します。


### 新しいサーバー上での操作

もし、早まってGrowiを開いてしまっていた場合

```shell-session
# ボリュームごと削除
$ docker-compose down --volumes
```

`docker-compose up`する前に、参照するDockerfile上で古い方で動いていたGrowiのバージョンと合わせておくこと。`dockekr-compose up`でボリュームを作ったらすぐに止めます。

```shell-session
$ docker-compose up -d
$ docker-compose stop
```

dockerボリュームを上書き展開します。

```shell-session
# -C オプションで / に対し var/lib/docker/volumes を展開します。
$ tar -xzvf path/to/growi_volumes.tar.gz -C /
```

最後にdocker-composeを再開します。

```shell-session
$ docker-compose start
```

これでバックアップ用の新しいユーザーを作成しなくても、従来のユーザーでログインできました。
画像は一部参照できないものもありましたが、ほとんどのページで画像が正しく表示されていました。
参照切れしているページとしていないページの差は分かりませんでした。古めのページの参照が切れているかな。

## 参考
[ubuntu環境のgrowi移行手順](https://www.tokiukaze.com/blog/growi-ubuntu/)

単純な話、/var/lib/docker/volumes/growi* 関連のデータをoldからnewへ移行すればいいだけのこと。

```
-rwxrwxrwx 1 u1and0 u1and0 663M  8月 10 11:22 growi_volumes.tar.gz
```

tar.gzにすると約600MBだった


これを利用して自動バックアップも取れそう。

今までは管理画面から手動バックアップだけとっていた。しかし、この方法では画像のバックアップが取れない。なぜならLocalに指定しているため！

画像の保存先をMongo/GridFSにしておけばよかったぁー
とはいえ今更悔やんでもしょうがない。
今更保存先をMongo/GridFSに変えたってこれまでアップロードした写真500点の参照が消えてしまい、永遠にアクセスできなくなってしまうため。
ただし、下の方法で参照がばらばらでもアップロードしたファイルだけは救済できる余地がある。



## やってだめだったこと

[Discussion: FILE_UPLOAD=local 環境下での Attachment 保存場所の予期しない変更(bug 含む)への対処について](https://github.com/weseek/growi/discussions/6086)

> v6.1.0 での変更
> 2023年5月にリリースを目指している v6.1.0 で、保存場所が再び変更されますのでまずは頭出しです。

> Before -> After
> /opt/growi/packages/app/public -> /opt/growi/apps/app/public

参考によると **/opt/growi/packages/app/public辺りに画像が含まれているらしい。**

**`docker exec -it growi_app_1` で潜り込んでtar.gzにしてアップロードファイル一覧をサルベージ**した。

しかし、これをnew docker composeのコンテナへコピーしたが、反映されなかった。
注意喚起：SimpleNoteのサーバで障害が発生しているのでご注意ください

公式フォーラム
https://forums.simplenote.com/forums/topic/simplenote-servers-performance-issues-august-2023/

SimpleNoteは、プレーンテキストでメモを残すことに特化した（現時点では）無料のサービスです。
2023年8月8日ごろからの同期不能・困難なシステム障害に伴い、新規ノートや変更が消滅する不具合が発生しているようです。
これはローカル側の問題ではなくSimpleNoteサービス側の問題のようなので、回避ができません。

エンジニアの方はこのサービスを利用している人も少なくないと思いますので、問題が解消されるまでクリティカルな使用を控えるようにしたほうがいいかもしれません。
【SwiftUI】ScrollViewをページングできるようにする

# はじめに
SwiftUIはiOS17からページングができるようになります。

https://qiita.com/SNQ-2001/items/55ca01f85e0761808f63

しかし、iOS16以下でもページングは使用したいです。
`SwiftUIIntrospect`を使用すれば実現できます。

# サンプルアプリ
![Simulator Screen Recording - iPhone 14 Pro - 2023-08-10 at 15.27.33.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/89155adb-3d0c-4ae8-aa05-abf3034615a8.gif)

# 実装
```swift
import SwiftUI
import SwiftUIIntrospect

struct ContentView: View {
    @State private var isLoading = false
    var body: some View {
        GeometryReader { proxy in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 0) {
                    ForEach(0..<50) { _ in
                        RoundedRectangle(cornerRadius: 10)
                            .frame(width: proxy.size.width)
                            .frame(maxHeight: .infinity)
                            .foregroundStyle(Color(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1)))
                    }
                }
            }
            .introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { scrollView in
                scrollView.isPagingEnabled = true
            }
        }
    }
}
```

# おわり
SwiftUIを使うなら`SwiftUIIntrospect`は必須ライブラリです
【PHP】西暦を和暦に変換する関数

PHPで西暦を和暦に変換する処理を書く機会があったため、備忘録として残します。

```php
function convertToJapaneseEra($year) {
    try {
        if ($year < 1868) {
            throw new Exception("1868年より前の年は変換できません。");
        }
    
        $eraData = [
            ["name" => "令和", "start" => 2019],
            ["name" => "平成", "start" => 1989],
            ["name" => "昭和", "start" => 1926],
            ["name" => "大正", "start" => 1912],
            ["name" => "明治", "start" => 1868]
        ];
    
        $japaneseYear = "";
        
        foreach ($eraData as $era) {
            if ($year >= $era["start"]) {
                $japaneseYear = $era["name"] . ($year - $era["start"] + 1);
                if ($year === $era["start"]) {
                    $japaneseYear .= "元年";
                } else {
                    $japaneseYear .= "年";
                }
                break;
            }
        }

        return $japaneseYear;

    } catch (Exception $e) {
        echo "エラー: " . $e -> getMessage();
    }
}
```

```php: 使用例
echo convertToJapaneseEra(2019); // 令和元年
echo convertToJapaneseEra(1192); // エラー: 1868年より前の年は変換できません。
```
ConohaVPSでKubernetes Clusterを構築

# Update to the latest 
sudo apt update
sudo apt -y full-upgrade
shutdown -r now


# Load br_netfilter module
modprobe br_netfilter
lsmod | grep br_netfilter



# Install pre-requisit
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF


# Apply sysctl params without reboot
sudo sysctl --system


# Install containerd
apt -y install containerd
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
systemctl restart containerd



# Install kubeadm, kubelet, kubectl
sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

# Set host name
sudo hostnamectl set-hostname \<New host name>

# Make swapp off
swapoff -a
sudo ufw allow 6443/tcp
(sudo ufw allow from \<other node IPs>)

# Execute only on the controlplane node
kubeadm init --apiserver-advertise-address=\<controlplane IP address> --pod-network-cidr=10.244.0.0/16

# Execute only on worker nodes
kubeadm join xxxx

# Execute only on the controlplane node
mkdir -p \\$HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf \\$HOME/.kube/config
sudo chown \\$(id -u):\\$(id -g) \\$HOME/.kube/config

export KUBECONFIG=/etc/kubernetes/admin.conf

# Deploy network plugin
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
Java SE環境でJakarta Bean Validationを使うための依存性

# 環境
- JDK 17

# 結論
```xml:pom.xml
    <dependencies>
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>8.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.expressly</groupId>
            <artifactId>expressly</artifactId>
            <version>5.0.0</version>
        </dependency>
    </dependencies>
```

> バージョンはその時で最新のものに変更してください。

# 説明
Hibernate ValidatorはJakarta Bean Validationの実装です。

Hibernate Validatorの動作にはJakarta Expression Language実装が必要です。

ExpressLyはJakarta Expression Languageの実装です。
賃貸アプリケーションで学んだことのアウトプット

### 今回製作したアプリケーションは、今まで作ったアプリケーションとは違い一つのcontrollerのアクションで、二つのmodelに登録・変更を行えるようにすることが最大の難所だったが、以下の4のメソッドを使ったら無事にアプリが作れた

#### 1.accepts_nested_attributes_forメソッド
accepts_nested_attributes_forメソッドとは、<font color="red">親モデルと紐付いている子モデルの値も一緒に保存ができるメソッドです</font>
今回のアプリケーションの場合だと、一つcontroller(controller名:houses_controller)で家の情報を登録する親のmodel(model名:house.rb)とその物件の近くの駅の情報を複数登録できる子のモデル(model名:station.rb)があり、入力された物件情報とその物件の最寄駅の情報を、DBは違いますが、controllerのcreateアクションが働くことで一緒に保存してくれます。

また、今回は、accepts_nested_attributes_forメソッドを以下のように記述しましたが、テーブル名の後にupdate_only: trueとreject_if: :all_blankと記述しましたが、この二つについても説明します

`accepts_nested_attributes_for :stations, update_only: true, reject_if: :all_blank`

`update_only: true`:この部分は、<font color="red">親モデルの更新時に子モデルの値も更新するようになります。</font>つまり、子モデルの新規作成や削除は行われず、既存の子モデルの値のみが更新されます。このオプションを指定しない場合、親モデルの更新時に子モデルの新規作成や削除も行われます。
`reject_if: :all_blank`:このオプションを指定すると、<font color="red">何も書いていない空の子モデルの属性を拒否し、無駄な空のレコードを作らないようになります。</font>具体的には、子モデルの値が何も入力されなかった（blank）である場合、その子モデルは無視されます。つまり、その子モデルは親モデルとの関連付けや保存の対象となりません。このオプションを指定しない場合、からの子モデルも親モデルとの関連付けや子モデルのDBへの保存の対象となり、何の値も入っていないレコードが作成されてしまいます。


#### 2.fields_forメソッド
fields_forメソッドは、<font color="red">親モデルと関連付けられた子モデルの入力欄を一つのフォームで表示させるため</font>に、viewファイルのnew, edit, もしくはパーシャルファイルに記述します。これにより、親モデルと関連する複数の子モデルに対して、作成・編集することができます。<font color="red">fields_forメソッドはform_withやform_forなどのフォームヘルパーの中で使われます。</font>
例えば、今回のアプリケーションの場合だと、家の情報を登録する親のモデル(model名:house.rb)とその物件の近くの駅の情報を複数登録できる子のモデル(model名:station.rb)があります。物件情報を登録する際にnewアクションで呼び出されたview画面では、物件の情報を入力する欄と最寄駅の情報を入力する欄が一画面でまとめて現れます(※画像1)。それぞれ入力された値はそれぞれのモデルを介して別々のhousesテーブルとstationsテーブルに保存されます。


#### 3.buildメソッド
buildメソッドとは、関連付けられたモデルのインスタンスを生成し、親モデルのインスタンスに自動的に紐づけるメソッドです。アソシエーションを利用してインスタンスを作成するときに便利です。
今回の例で言うとnewアクションとeditアクションにインスタンス変数.テーブル名.build(@house.stations.build)と記載してあげることかつ、viewファイルにfields_forメソッドを定義してあげることで、簡単に駅情報の入力画面呼び出すことができます。さらに、newアクションにも書いてある、timesメソッドで使いくり返し処理の値を決めることで、fields_forメソッド直下に作った入力欄を返し処理の値分、出力させることができます。今回は、2.timesとしているため、（※画像1）のように駅情報を入力する画面を2つ出しています。(※画像1)(※画像2)



#### 4.ストロングパラメータでのattributesメソッド
ストロングパラメータでのattributesメソッドは今回の場合、親モデルであるHouseと子モデルであるStationの属性を同時に保存するためのパラメーターです。これにより、new画面などで情報を登録した際に親である物件の情報と子である駅の情報の２つにストロングパラメーターが適用されます。
`def house_params`
    `params.require(:house).permit(:house_name, :rent, :address, :house_age, :remarks, `
    `stations_attributes: [:near_station_name, :line_name, :walk, :_destroy, :id])`
`end`
上記のコードの_destroyとidですが、_destroyは子モデルのレコードを削除するときに必要です。_destroyを許可することで、親モデルに紐づく子モデルのレコードを特定し、そのレコードをデータベースから削除できます。_destroyがない場合は、レコードの削除ができません。なので今回は、Houseモデルに紐づくStationモデルのレコードを削除するときには、以下のように_destroyを含める必要があります。
idは子モデルのレコードを更新するときに必要です。idを許可することで、親モデルに紐づく子モデルのレコードを特定し、その属性を変更できます。idがない場合は、新しいレコードが作成されます。なので、既存のレコードを更新したい時にはidは必須です。

### 以下、画像
※画像1
![スクリーンショット 2023-08-10 13.40.24.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125392/864693c3-4d66-5efc-ea46-bd9a65135f6c.jpeg)
※画像2
![スクリーンショット 2023-08-10 14.13.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125392/1bf88845-af95-bcf0-bc74-4991c60af895.png)
[Swift]safariを起動してリンクを開くコードの作成

テキストをリンクとして実装するためには、UITextViewを使用することができます。以下に、テキストをリンクとして表示し、タップすると https://www.google.com にアクセスするコード例を示します。

1. まず、Storyboard上にUITextViewを配置します。
1. UITextViewを配置したら、そのUITextViewをViewControllerのコードと接続します
1. ViewControllerのコードに、以下のコードを追加します。

```
import UIKit
import SafariServices

class ViewController: UIViewController, UITextViewDelegate {

    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the text and link attributes for the UITextView
        let attributedText = NSMutableAttributedString(string: "Visit Google")
        attributedText.addAttribute(.link, value: "https://www.google.com/", range: NSRange(location: 0, length: attributedText.length))

        textView.delegate = self
        textView.attributedText = attributedText
        textView.isUserInteractionEnabled = true
        textView.isEditable = false
    }

    // UITextViewDelegate method to handle link tap
    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        let safariViewController = SFSafariViewController(url: URL)
        present(safariViewController, animated: true, completion: nil)
        return false
    }
}
```
このコードでは、UITextViewを使用してテキストを表示し、そのテキストをリンクとして扱うためにattributedTextを使用してリンク属性を設定しています。shouldInteractWithメソッドは、リンクがタップされた際に呼ばれ、SFSafariViewControllerを使用してリンク先にアクセスします。

これにより、テキストをリンクとして表示し、タップするとSFSafariViewControllerを使用してhttps://www.google.com/にアクセスできるようになります。
Azure Databricks にて共有モードのクラスターを作成する項目が表示されない場合の対応

## 概要

Azure Databricks にて 共有クラスターを作成する項目が表示されない事象に少しつまづいたため、対応方法を共有します。価格レベルが Standad となっていることが原因であり、Premium にアップグレードすることで解決できます。Starndard の場合には、下記の画像のように`共有`アクセスモードを選択することができません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/fa58a4d5-777e-a37c-c493-e6e4fb1f2f0f.png)


## エラー原因

共有モードのアクセスモードを利用するには、Premium が必要となる旨が記載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/85795c99-0fa1-ff77-0b15-923f68c319e7.png)

引用元：[クラスター アクセス モードとは? - Azure Databricks | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/databricks/clusters/configure#--what-is-cluster-access-mode)

価格レベルを確認するには、Azure Portal にて確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d919c2e0-7a6b-da24-482b-5294a79cc64a.png)

## 対応方法

### 1. Azure Portal にて Databricks のリソースを表示後、価格レベルの`Standard (Apache Spark、Azure AD でセキュリティ保護) (Click to change)`を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d919c2e0-7a6b-da24-482b-5294a79cc64a.png)

### 2. `Upgrade Azure Databricks`ウィンドウにて、`Upgrade`を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e16f2106-ce7c-08a4-6422-60312374035d.png)

### 3. 数分後、価格レベルが`Premium (+ ロールベースのアクセス制御) (Click to change)`に変更されたことを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/b0512434-854e-7c71-1856-b115d153b204.png)

### 4. Databricks Workspace にログイン後、共有アクセスモードのクラスターを作成できることを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/278adb75-4734-d852-8285-3404698d1c04.png)
resourceとresourcesの違い on Rails

# resource と　resourcesの違い

このサイト曰く、
[resourceとresourcesの違い](https://techtechmedia.com/resources-resource-difference/#:~:text=%E7%B5%90%E8%AB%96%E3%81%8B%E3%82%89%E8%A8%80%E3%81%86%E3%81%A8%E3%80%81%E3%80%8Cresources,%E3%81%8C%E7%94%9F%E6%88%90%E3%81%95%E3%82%8C%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82)

> 「resourceメソッド」にはidが付与されていません。ということはつまり、リソースを絞り込めない（絞り込まない）状況で使用します。<br>
その一方で「resourcesメソッド」はidが付与されています。そのため、複数あるリソースの中からidを用いて特定のリソースを絞り込むことができます。<br>
まとめると、複数存在するリソース（商品やユーザーなど）では「resources」を使用し、１つしか存在しないリソースには「resouece」を使用します。

わかりやすい。

あと、resourceでは一つのリソースしかない（resourcesみたいに複数のユーザがいたりしない）のでindexアクションが必要ない。だからresourceではindexアクションのルートは生成されない。
[23c Oracle] ORAdiffツールリリース！超簡単。2つのDBでパッチレベルの機能差異比較

## やれること
2つのOracleデータベースでリリース間の違いを知りたいと思いませんか？
私は現在、19cと23cを比較して、機能差異を調査していました。

そんななか、ORAdiffというすごいツールがリリースされました
メジャーリリースどころか、パッチレベルで比較できます！

## ORAdiffツールへのアクセス
Oracle.comのIDが必要です。

:::note info
https://oradiff.oracle.com
:::


## 使用例

### 初期化パラメータ比較
19c と 23cを、初期化パラメータごとに、デフォルト値や、PDFでの変更有無を確認できます。
画面上部から、比較対象のバージョンを選ぶだけです。
細かいパッチレベルまで選択できるため、19.19 と 23cの比較なども可能です。

画面真ん中のタブ「Added , Removed , Changed」を選ぶと
増えた、減った、変更された　が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/bc3512b2-543f-8d8b-e82c-227595d99f27.png)


### デフォルトユーザの比較
デフォルトで存在するDBユーザの有無（追加・削除）や、変更されたデフォルト値が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/69fb871e-9014-ca3b-e627-192333b4c6fe.png)


### バグフィックスがふくまれるか？
特定のパッチに、あるバグフィックスが含まれるか簡単に確認できます。
番号を指定して検索したり、一覧で表示可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/30769871-8f7a-55ce-9a1d-b24f013a6b7f.png)
[Unity 3D]一個一個のGameObjectに色を付けてみる

Unityで、クローン一個一個に、それぞれ違った色を付けてみたいと思ったため、
Scriptを使って色を付けてみることにしました。
しかし、私はプログラミングもQiitaも初心者なので、色々とおかしいところがあると思いますが、
お許しください。
## 使用Unityバージョン
2020.3.4f1

<h2>今回の目標</h2>
下の画像のように、ランダムに色を付けれるようになる

<h2>実践</h2>
まずは、クローンを作れるように、適当にキューブのプレハブを用意します。
そして、PrefabCreateというスクリプトを書いていきます。

```C#:PrefabCreate.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PrefabCreate : MonoBehaviour
{
    [SerializeField] private GameObject cube; // プレハブのGameObject

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(cube, new Vector3((Random.value - 0.5f) * 10, (Random.value - 0.5f) * 10, 0), Quaternion.identity);
        }
    }
}
```
これに関しては適当です。今回はスペースキーを押すとキューブが生成されるようにしました。
これを適当なオブジェクトにアタッチしてあげて、CubeのところにPrefabをアタッチします。
<b>ここからが本題です。</b>色を変更するためのスクリプトを作ってあげます。
名前は... うーん、とりあえず適当にChangeColorとかにしておきます。

```C#:ChangeColor.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChangeColor : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Renderer renderer = this.gameObject.GetComponent<Renderer>();
        if (renderer != null)
        {
            Material material = new Material(Shader.Find("Standard"));
            material.color = Color.HSVToRGB(Random.value, 1f, 1f);
            renderer.material = material;
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
```
<details><summary>解説</summary>
まずは、Renderer renderer = this.gameObject.GetComponent<Renderer>();についてです。
これには、Materialをアタッチできるので、自分自身のRendererを取得しています。
次に、Material material = new Material(Shader.Find("Standard"));についてです。
これに関しては、materialをスクリプト内で作成し定義する、ということです。
Shader.Find("Standard")については、実際自分でもよくわかっていません。
下手に間違っている可能性のある情報を載せるのは良くないのでここは解説を省いていただきます。
そして、material.color = (Color型);についてです。
これはそのままで、materialの色を指定しています。
そして最後、renderer.material = material;についてです。
これはGameObjectのRendererのマテリアルのところに、materialをアタッチしているのと同じ
動作になります。
以上で解説終わりです。
</details>

## 結果
実行してスペースキーを連打するとこのようになるはずです。
![スクリーンショット 2023-08-10 135016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3530003/ef48fb90-94ab-1acc-b1b7-7dc807606ed0.png)

## 結論
スクリプトで、このような手順を踏めばいいです。
・対象のGameObjectからRendererをGetComponentする
・Materialを定義してやる
・定義したmaterialのcolorプロパティに色情報を代入
・取得したrendererのmaterialプロパティに定義したmaterialを代入
これによってそれぞれ違った色を付けることができます。

今回の記事は以上です。お読みいただきありがとうございました。
私たち「組込屋（エンジニア）」はどこへ行く？（その３）

前回の記事（https://qiita.com/Cente_mw/items/5ea603bdc2e9afb10a02 ）で、自社の技術レベルを落とすことなく、かつ、「餅屋は餅屋」として、本業の部分での切磋琢磨で商品価値を高めて、市場で勝ち残っていく必要があるという話をしました。そんな中で、ミドルウェア屋の私が言うのも眉唾モノですが、買って動いて安心なミドルウェアが買えるのであれば、それを買って製品化するのが良いんじゃないですか？っという話もしました。

今回は、「買えるのであれば」の話をしたいと思います。
私が言うのも何ですが、ミドルウェアって無償のモノも多くありますし、その性能も外から見たらそんなに違いが分からないんじゃないかと思うんです。「サポートが良いですよ！」と言われても、絵に描いた餅かもしれませんよね？
そんな商品がいっぱいある中で、どうやって「予算」を確保して、購入しますか？　予算確保の段階で、「どうしてこの商品が良いと思ったんですか」と聞かれたらどうしますかね？　一回でもその商品使った事あれば、「実績」でお話が出来ると思うのですが。

最近、「初月無料キャンペーン」とか、「＊＊月無料のお試しキャンペーン」とか、よく聞きますよね。
サブスクリプションライセンス（サブスク）と言われるのですが、月々の定額支払いの「コース」に加入してもらって、安定的な売上（利益）を得たいとする新しい売り方、買い方ですね。
そう、これ、「売り方」であると同時に「買い方」でもあることに注目です。売り方側から見ると、先に書いた通り、商品に価値を感じ続けてもらって、一括契約だと二の足を踏むような金額を月毎に比較的少額で契約を継続してもらって、安定的な収入としたいというものですね。さて、買い方側から見るとどうでしょう？　支払い額を少額にして、まず試せる。【フル】に楽しんでみる。期待外れだったらすぐに解約（最低継続期間はあるかもしれませんが）する。リスク最小での「お試し」ですよね。
サブスク＝お試し　とも定義できるわけですね。（ある意味、あたりまえ？）

はい。<b>私、ミドルウェア屋です。（笑）</b>
ミドルウェアって、「お試し」ってありますか？　一部ありますね？　「評価ライセンス」とか「評価パック」とか、試せる環境を提供しているところもありますね。さてさて、先の文章を読み返してみてください。【】がついていたところです。
そう、それって【フル】に評価できるでしょうか？　以前の記事で、「フルソースコードで、改変権や使用権が明確で、サポートも充実していて」そんなミドルウェアを空洞化の充てとして選択しては？っという話をしました。
先ほどの「評価ライセンス」に代表される「試せる」環境は、フルではない事が多いです。ミドルウェア屋の中の人である私から言わせると、当たり前ですよね。「お試し」なのに、すべての事ができる【フル】で提供してしまって、支払額がミニマムだと、商売になりませんから。そりゃ、無いでしょう。。。となるはずです。

でも、今回、その【フル】で、イニシャルミニマムなライセンスを世に発表することにしたんです。
https://www.cente.jp/release/4669/

PoCライセンス。これ、試せる環境としては【フル】です。これまで提供してきたフルソースコードからなにも削らず、付随するサポート条件も削っていません。フルです。ですが、ただ１点だけ、「商用利用だけは勘弁」となっています。
「お試し」の条件としては、これでどうでしょう？
更に、「お試し」なんだから、使用する環境（通常はCPU縛り）も無制限としました。そして、なんと定価80万円のパッケージが月々2万円です。これならば、大きな予算を取らずに「お試し」していただけるのではないでしょうか？

このライセンスの「肝」は、実は「量産フェーズライセンス」というところに書いてある条件「バイナリ利用可（ソースコード改変不可）」という項目なのです。少し難解ですが、最終量産状態で、月々の支払を止めても「ソースコードが手元に残る」んです。
エンジニアが考えた、エンジニアの為のPoCの条件、そして、PoCから始まった開発の製品化のゴールで求める条件、、それを形にしたPoCライセンスなんです。

この「難解」なライセンスに秘められた、エンジニアでなければ設定できない「譲れない条件」については、次回の記事で。


Cente：
https://www.cente.jp/

お問合せはこちら：
https://www.cente.jp/otoiawase/

# ■次回
私たち「組込屋（エンジニア）」はどこへ行く？（その４）→Cente PoCライセンスへ！
https://qiita.com/Cente_mw/items/11b1cb2a73b3a42ba957