OmniAICreator/Qiita-1.07M huggingface dataset:
Reactで下にスクロールしたら消えて上にスクロールしたら出てくるやつ作った

## 作ったもの
これです。
![画面収録 2023-06-13 22.58.14.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112946/212d11cb-74d8-8985-f7fa-ef1ad3c5ae6c.gif)

スクロールで出たり消えたりするコレ、なんて呼ばれてるんでしょうかね。
ちょうどこれが使いたくて探してみたものの名称が分からないのでうまく検索できず、いくつか見つかったやつも出てるか消えてるかの0、1の状態のものしかなかったので自分で作ってみることにしました。


## 用意するもの
- React
- 使い慣れたエディタ

お好みで
- TypeScript
- TailwindCSS

## 作り方
### 実装イメージ
- stickyな要素が元の場所にいるとき、ネガティブな値を指定しても表示位置が変わることはない
- stickyな要素が張り付いているとき、ネガティブな値を指定すると指定した位置に表示される

事前に試してみた結果上記のことが確認できたので、下にスクロールすれば（消す場合）現在の位置から移動した分だけマイナスしていき、上にスクロールすれば（出す場合）現在の位置から移動した分だけプラスしていけば消したり出したりできそうです。

また、stickyな要素はいつも通り実装し、その要素を `display:contents` な要素でラップする感じで実装すればわりと機能だけに集中して作れそうな気がします。

### 実装

```typescript
"use client";

import { useEffect, useRef } from "react";

export type HideStickyProps = {
  children: React.ReactNode;
  placement: "top" | "bottom";
  max?: number;
  min?: number;
};
export function HideSticky({
  children,
  placement,
  max = 0,
  min,
}: HideStickyProps) {
  const el = useRef<HTMLDivElement>(null);
  const currentOffset = useRef(max);
  const currentScrollTop = useRef(0);

  useEffect(() => {
    const sticky = el.current?.firstElementChild as HTMLElement;
    let { height } = sticky.getBoundingClientRect();
    currentScrollTop.current = document.documentElement.scrollTop;

    // サイズ変更を反映する
    const observer = new ResizeObserver(() => {
      height = sticky.getBoundingClientRect().height;
      if (min == null) {
        handleScroll();
      }
    });
    observer.observe(sticky);

    function handleScroll() {
      const before = currentScrollTop.current;
      currentScrollTop.current = document.documentElement.scrollTop;
      const scroll = before - currentScrollTop.current;

      currentOffset.current = Math.min(
        max,
        Math.max(min ?? -height, currentOffset.current + scroll)
      );

      sticky.style[placement] = `${currentOffset.current}px`;
    }
    window.addEventListener("scroll", handleScroll);

    handleScroll();

    return () => {
      window.removeEventListener("scroll", handleScroll);
      observer.disconnect();
    };
  }, [placement, max, min]);
  return (
    <div ref={el} className="contents">
      {children}
    </div>
  );
}

```

### 解説

`display:contents` なラッパー要素から直下のstickyな要素を取得します。

現在のスクロール位置を保存しておいて、あとはスクロールイベントが発火するたびにスクロールした分だけ現在要素の位置から動かしていくだけです。

ただ、そのままだとどこまでも消えていってしまうので表示の最大、最小位置を設定しておきます。

この実装では最小位置を要素の高さ分としているので（普通は気にする必要ないけど）要素の高さの変更を `ResizeObserver` を使って監視しています。
（いつのまにか現れたobserver３兄弟本当に便利）



## 使い方

いつも通り実装したstickyな要素を今回作ったコンポーネントでラップします。

```jsx
<HideSticky placement="top">
  <header className="sticky top-0">
  ...
  </header>
</HideSticky>
```

## まとめ

なんとなく作ってみましたが、自分の持っているデバイスでは案外いい感じに動いているようです。

iPhoneは持っていないのでiPadのSafariで確認したところやや引っかかる感じがしたものの、機能をとるか完璧な見た目をとるかを選べるくらいにはなっているのではないでしょうか。
（もっと古い端末だとどうかは分かりません）

ちなみにiPadのSafariのときだけCSSのTransitionで出てるor消えてるの0,1モードを入れてみたけど対して変わらなかったので消してしまいました。

元々JSで実装していた機能がどんどんブラウザのAPIとして実装されていっているので、アドレスバー等で既に良く使われているこの機能も早く実装されるといいなと思います。

それにしてもなんていう名前なんでしょうね、これ。
Kubernetes入門！主要コンポーネントを概要図で学ぼう

調べたらいっぱい出てくるかと思いきや、意外といいのが無かったので自分が理解しやすいように描いてみました。

# そもそもKubernetesとは？
一言でいうと「コンテナ管理ソフトウェア」です。

https://speakerdeck.com/minorun365/kontenatutehe-kubernetesru-men

オープンソースソフトウェア（OSS）なので、オンプレミスや各種パブリッククラウドなど様々なインフラストラクチャ上で利用することができます。


# 概要図
Kubernetesの主要コンポーネントは以下です。
![スクリーン ショット 2023-06-13 に 23.00.10 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/fa7403a2-207e-7697-2d79-6faa5aa18b86.png)

※今回は分かりやすいよう、各コンポーネントを抽象的な役割名ではなく具体的な実装名で表現しています。

### コントロールプレーン
「管理サーバー」と捉えると分かりやすいかも知れません。
自分でサーバーを立ててセットアップすることもできますが、パブリッククラウドではマネージドサービスとして提供されています。（例：AWSのEKSなど）
- kube-apiserver：コントロールプレーンのフロントエンドとなるAPIサーバー。管理者からの操作を受け付け、各コンポーネントとやり取りする
- kube-controller-manager：「サービス」や「デプロイメント」などの各k8sオブジェクトの司令塔となるコントローラーたちを管理する
- kube-scheduler：作成されたPodとノードのアサインを決定し、etcdに書き込む
- etcd：クラスターの「あるべき状態」が記録されるキーバリューストア

### ノード（データプレーン）
実際にコンテナが動く土台サーバーの部分を指します。
- kubelet：ノード側のエージェント。自ノード内のPodが「あるべき状態」かを監視する
- kube-proxy：クラスター内外からPodへのネットワークルールを管理してiptablesを更新する
- containerd：Podを実行するためのコンテナランタイム


# ぜひ自分で触ってKubernetesを動かしてみよう！
手前味噌ですが、AWSを用いたハンズオン記事を以前に書いたのでよければハンズオンしてみてください。

https://qiita.com/minorun365/items/0441e4878f0984a9fc0a


# 参考文献
https://kubernetes.io/ja/docs/concepts/overview/components/

https://cstoku.dev/posts/2018/k8sdojo-24/

https://zenn.dev/khokohokok/articles/7b6f49ac9b2151
The emulator process for AVD XXX has terminatedでAVDが起動しない

Android Virtual Device(AVD)を作成して、起動しようとすると以下のようなエラーが発生することがあります。
```
The emulator process for AVD XXX has terminated.
```
他のサイトを見てもディスクの空き容量不足が原因と書かれていて解決しなかったのですが、解決したので原因と解決法を残しておきます。

## 発生原因
おそらく、`Emulated Performance`の`Graphics`を`Hardware -GLES XXX`に設定しているはずです。
この設定を行うとハードウェアアクセラレーションが有効になり、GPUを使用してAVDの処理を行います。
したがってこのエラーが出る原因は、GPUドライバーに何らかのエラーがある、またはドライバーが正常に当たっていない可能性が高いです。

## 解決方法

### 1. `Software - GLES XXX`に設定する
この設定ではGPUのハードウェアアクセラレーションを無効にし、CPUパワーでAVDを起動します。
ある程度のCPUであれば多少重たくとも動作するはずです。

### 2. GPUのドライバーを正しく設定する
正しくドライバーが設定できればハードウェアアクセラレーションが使用できます。
実際に試してみたところ、`Hardware -GLES XXX`を有効にしても正常に動作することができました。

LinuxでNVIDIAのカードを使用している場合、
```sh:shell
$ nvidia-smi
```
と入力してください。そこで以下のような出力になればドライバーが正しく当たっています。
```
Tue Jun 13 23:35:50 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 530.41.03              Driver Version: 530.41.03    CUDA Version: 12.1     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                  Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf            Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce GTX 980 Ti       Off| 00000000:01:00.0  On |                  N/A |
| 27%   66C    P0               65W / 250W|    369MiB /  6144MiB |      4%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A       529      G   /usr/lib/Xorg                               129MiB |
|    0   N/A  N/A       584      G   /usr/bin/gnome-shell                         12MiB |
|    0   N/A  N/A       876      G   /usr/bin/kgx                                 30MiB |
|    0   N/A  N/A      1127      G   ...144 --enable-features=WebUIDarkMode      164MiB |
|    0   N/A  N/A      3631      G   ...,WinRetrieveSuggestionsOnlyOnDemand       15MiB |
+---------------------------------------------------------------------------------------+
```
もしこのような出力にならなければ適宜OSやディストリビューションにあった方法でNVIDIAドライバーまたはRadeonドライバーをインストールしてください。


## 参考文献
https://developer.android.com/studio/run/emulator-acceleration?hl=ja
インボイス対応進んでますか？安心してください。適格請求書発行事業者公表システムWeb-APIのラッパーAPIがありますよ。

インボイス制度が2023年10月から始まります。国の方針なため、仕事でもインボイスへの対応を予定している方が多いのではないでしょうか。

行政が作成した資料を読み解きながら、開発に落とし込んでいく。
大変ですよね。

そんなエンジニアに朗報です。

*安心してください。適格請求書発行事業者公表システムWeb-APIのラッパーAPIがありますよ。*

# 開発したもの
国税庁が提供している、インボイス制度適格請求書発行事業者公表システムWeb-APIのクライアントAPIをライブラリにし、OSSとして公開しました。名前はkendamaです。
公開したライブラリは、RubyとPython製のものを公開しています。

https://github.com/nisyuu/kendama

https://github.com/nisyuu/kendama-python

Rubyであれば、RubyGemsにも登録しているので`bundle install kendama`でインストールができます。

https://rubygems.org/gems/kendama

Pythonの方は、`pip install kendama`でインストールが可能です。

もし、使ってみて改善点などが見つかったらIssueにぜひ課題を挙げてみてください。プルリクエストも喜んでお待ちしています。

# kendamaの使い方
使用方法はREADMEにも書いていますが、こちらにもRubyの場合の使い方を簡単に記します。
デフォルトの状態だと、APIのリクエスト先は検証環境に向いているのでご安心ください。

また、コードを実行する場合はアプリケーションIDが必要となるので忘れずに。

## 登録番号を指定して情報を取得

```ruby
require 'kendama'

api_instance = Kendama::V1Api.new
id = 'アプリケーションID'
number = '登録番号'
type = '21'
opts = {
  history: '0'
}

begin
  result = api_instance.get_announcement_by_number(id, number, type, opts)
rescue Kendama::ApiError => e
  puts "Error when calling V1Api->get_announcement_by_number: #{e}"
end

```

検証環境の場合、`T0000000000016`や`T0000000000017`などの登録番号がいくつかテストデータとして入っているようです。

## 取得期間を指定して情報を取得

```ruby
require 'time'
require 'kendama'

api_instance = Kendama::V1Api.new
id = 'アプリケーションID'
from = Date.parse('Tue Oct 01 09:00:00 JST 2024')
to = Date.parse('Tue Oct 01 09:00:00 JST 2024')
type = '21'
opts = {
  division: '1',
  divide: 'divide_example'
}

begin
  result = api_instance.get_announcement_by_diff(id, from, to, type, opts)
rescue Kendama::ApiError => e
  puts "Error when calling V1Api->get_announcement_by_diff: #{e}"
end
```


## 登録番号と日付を指定して情報を取得

```ruby
require 'time'
require 'kendama'

api_instance = Kendama::V1Api.new
id = 'アプリケーションID'
number = '登録番号'
day = Date.parse('Fri Dec 01 09:00:00 JST 2023')
type = '21'

begin
  result = api_instance.get_announcement_by_valid(id, number, day, type)
rescue Kendama::ApiError => e
  puts "Error when calling V1Api->get_announcement_by_valid: #{e}"
end
```

# その他の仕様

リクエストのクエリパラメーターや、レスポンスボディなどのAPI仕様についてはkendamaのリポジトリにドキュメントを用意しているので、必要な方はご覧ください。

https://github.com/nisyuu/kendama/tree/main/docs
ASP.NET Core でローカルにシークレットをサクッと用意する

API の接続キーをデバッグ実行時に安全に取り扱いたいですよね。
ハードコードしてリポジトリにプッシュなんかしちゃいけない。

ASP.NET Core と VisualStudio の開発環境だったら、とっても簡単に管理できます。

# 環境

Microsoft Visual Studio Community 2022 (64 ビット) - Current
Version 17.6.2

.NET 6

# 手順

## 1. ユーザーシークレットを追加する

1. プロジェクトファイルを右クリック
1. [ユーザー シークレットの管理(G)] をクリック
1. `secrets.json` がテキストエディタ―で開かれるのでシークレットを追加する

```json:secrets.json
{
  "Demo": {
    "Secret": "demo-secret"
  }
}
```

:::note
JSON ファイルは以下に保存されます。
`%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json`

このプロジェクトをプルした人は、[ユーザーシークレットの管理(G)] をクリックするとプロジェクトに設定された `<user_secrets_id>` で JSON ファイルが作成されるので、そのファイルにシークレットを書いてあげれば OK です。
:::

## 2. IConfiguration を DI してシークレットを取得する

ASP.NET Core では何も設定せずに `IConfiguration` が DI されます。受け取る部分だけ実装してあげれば簡単にシークレットを取得できます。
今回は、ASP.NET Core MVC プロジェクトを新規作成したときの `HomeController` で上記シークレットを使ってみます。

1. `IConfiguration` をコンストラクターで DI する
```diff_c_sharp:HomeController.cs
+   private readonly IConfiguration _configuration;
    private readonly ILogger<HomeController> _logger;

    public HomeController(
+       IConfiguration configuration,
        ILogger<HomeController> logger)
    {
+       _configuration = configuration;
        _logger = logger;
    }
```

2\. `Index()` メソッドでシークレットを取得してみる

```diff_c_sharp:HomeController.cs
public IActionResult Index()
{
+   IConfigurationSection config = _configuration.GetSection("Demo:Secret");
+   string value = config.Value;
+   if (string.IsNullOrEmpty(value))
+   {
+       _logger.LogError("Empty configuration!");
+   }
+   else
+   {
+       _logger.LogInformation("Value: {Value}", value);
+   }
+
    return View();
}
```

3\. デバッグ実行して確認

```console
info: HigeDaruma.WebAppDIDemo.UI.AspNetCoreMvc.Controllers.HomeController[0]
      Value: demo-secret
```

あっという間にできました。これでソースコード上にシークレットを書く必要がなくなりました。
運用環境では Azure App Service などの環境変数としてシークレットを設定してあげれば良いでしょう。
いや、Key Vault を使わなきゃならないか・・・

# 参考

https://learn.microsoft.com/ja-jp/aspnet/core/security/app-secrets?view=aspnetcore-6.0&tabs=windows
Java

# Javaとは
Javaとは、プログラミング言語の一つ。
200種類以上あるプログラミング言語の中で昔からよく使わている。
応用力がある言語として昔から根強い人気を誇る。

Javaは基本的にどんな環境でも使える言語というのが特徴。
大企業での大規模システム開発やAndroidアプリの開発を得意としている。

オブジェクト指向言語であり、人気の高い言語である。

単価としては下の画像のような順位になっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412438/4b2c6275-62a7-23e6-2675-d4051ed7d06a.png)
https://freelance.levtech.jp/guide/detail/1507/
# 特徴
* 処理速度が速い
* 安定性やセキュリティが高い
* ドキュメントが豊富にある

# フレームワーク
### Web系
* Spling
* Jakarta EE(旧 Java EE)
* Apache Struts
* Apache Wicket
* Play Framework
* Spark Framework
* JSF(JavaServer Faces)
* SAStruts (Super Agile Struts)
* GWT(Google Web Toolkit)
* Grails
* DropWizard

### android
* Android Java

### その他
* 組み込み系
* 商用システム
* デスクトップアプリケーション

# 歴史
1996年 サン・マイクロシステムズによって市場リリース
2010年 オラクルに吸収合併されたことによりJavaの版権を移行

# 資格
* Javaプログラミング能力検定試験
* Android技術者認定試験
* Oracle認定Javaプログラマ(Oracle Certified Java Programmer)




# 参考記事
avaとは？言語の特徴や用途を初心者向けにわかりやすく解説
https://www.sejuku.net/blog/3686
Javaフレームワークのまとめ【2023年版】
https://freelance-start.com/articles/68#title8
【初心者向け】Javaの歴史を一通りなぞってみる
https://eng-entrance.com/java-history#Java
SpringBoot　アノテーションについて


# はじめに
　私は研修の中でSpringBootを使用しておりましたが、現在オリジナルアプリ作成の中で、SpringBootを使用していますが、研修の中で理解が曖昧だった点や今回気づいた点を今後、自分自身への備忘録も兼ねてあげていこうと思います。
間違った解釈をしている箇所などありましたらコメント等でご指摘いただければと思います。

# 各アノテーションについて
## @Autowired
このアノテーションをつけることで、都度newでインスタンスを生成する必要がなくなる。
すべてのクラスのインスタンスの生成に使えるわけではなく、使われる側で@Component/@Controller/@Service/@Repositoryといったアノテーションが付与されていることで、newせずにインスタンスの生成が可能。
@Componentなどのアノテーションがついていないクラスを@Autowiredで呼び出してもNullPointerExceptionが発生する。

@Autowired
```java
  Sample sample;
  //@Autowiredがないと↓
  Sample sample = new Sample();
```
## @PostMappingと@GetMappingの違い
1.使用するメソッドの違い：
・@GetMappingはGETメソッドに対してマッピングする。
・@PostMappingはPOSTメソッドに対してマッピングする。
2.リクエストパラメータの扱いの違い:
・@GetMappingでは、リクエストパラメータをURLのクエリパラメータとして受け取る（例：/example?param=value）。
・@PostMappingでは、リクエストパラメータをリクエストボディ内に含めて送信する。
3.リクエストデータの安全性の違い:
・@GetMappingは、リクエストパラメータがURLに含まれるため、情報がURLに表示される。
・@PostMappingは、リクエストボディ内にデータを含めるため、情報がURLに直接表示されず、より安全なデータ送信が可能。

## @RequestParam
個々のリクエストパラメータを直接受け取る。
コントローラメソッドの引数に付けることで、HTTPリクエストのクエリパラメータやフォームパラメータを受け取ることができる。
@RequestParamアノテーションには、いくつかのオプションな属性が存在する。
・required: パラメータが必須かどうかを指定する。デフォルトはtrueですが、falseに設定すると必須ではなくなる。
・defaultValue: パラメータのデフォルト値を指定する。パラメータが指定されていない場合に使用される。

## @ModelAttribute
オブジェクトとしてリクエストパラメータを受け取る。
@ModelAttributeアノテーションを使用してオブジェクトを受け取る。リクエストパラメータの名前とオブジェクトのフィールド名が一致していれば、自動的にバインディングされる。
@ModelAttributeアノテーションには、いくつかのオプションな属性がある。
・required: パラメータが必須かどうかを指定する。デフォルトはtrueですが、falseに設定すると必須ではなくなる。
・binding: オブジェクトがバインディングされるかどうかを指定する。デフォルトはtrueですが、falseに設定するとバインディングされなくなる。

## 参考サイト
https://springhack.com/autowired-%EF%BC%88springboot%E3%81%AE%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%89/
【Vuetify】スクロールと高さ指定がある要素内で$vuetify.goTo()を効かせる

## やりたいこと

業務で以下のような
ボタン押下で「overflow-y:auto」と「height」が効いている
divタグ内でスクロールさせたい要望があり、多少詰まったが解決したのでメモ
![Vuetify goTo exsample - Google Chrome 2023-06-13 22-53-46.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773736/5c587eec-27f5-8de4-d089-c96522a3e857.gif)


## やっていること
$vuetify.goTo()の第一引数に移動先の要素、第二引数に
移動先の要素を囲っている親要素を指定するとうまくいく。
## コード例
https://codepen.io/shota-1314/pen/gOdPYxJ

```javascript
new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data () {
    return {
    }
  },
  mounted() {
  },
  methods: {
    scrollToSection(number) {
      // 移動先親要素
      const container = document.querySelector('.scroll-container');
      const el = document.getElementById('card'+number);
      this.$vuetify.goTo(el,{container:container});
    }
  }
})
```

```html
<div id="app">
  <v-app id="inspire">
    <v-container>
      <v-row>
        <v-col id="button">
          <v-btn  @click="scrollToSection(1)">カード1</v-btn>
          <v-btn  @click="scrollToSection(2)">カード2</v-btn>
          <v-btn  @click="scrollToSection(3)">カード3</v-btn>
          <v-btn  @click="scrollToSection(4)">カード4</v-btn>
          <v-btn  @click="scrollToSection(5)">カード5</v-btn>
        </v-col>
      </v-row>
      <v-row class="border scroll-container">
        　<v-col>
        <v-card id="card1" class="mb-3" height="200">
          カード1
        </v-card>
        <v-card id="card2" class="mb-3" height="200">
          カード2
        </v-card>
           <v-card id="card3" class="mb-3" height="200">
          カード3
        </v-card>
           <v-card id="card4" class="mb-3" height="200">
          カード4
        </v-card>
           <v-card id="card5" class="mb-3" height="200">
          カード5
        </v-card>
        　</v-col>
        </v-row>
    </v-container>
  </v-app>
</div>
```

```css
<style>
.border{
  border:solid;
}
.scroll-container {
  height: 70vh;
  overflow-y: scroll;
}
</style>
```

## 補足
クラス指定でheightとoverflow-y: scrollを指定
している要素を取らないとうまく動作しない。


## 参考文献
https://v2.vuetifyjs.com/ja/features/scrolling/#section-4f7f304465b9
github にパスワードレスでpushする方法(備忘)

パスワードレスでgithubにpushするのにちょっと手間取ったので備忘。

1. SSHの鍵生成
`ssh-keygen`コマンドを使用。 (画像はLinux, Windowsでも同じコマンドを使用可能)
ファイル名(ここでは、`id_github_rsa.pub`)と生成用パスワード(無しでも可能)を入力する。
![keygen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/0d78d339-322c-4908-8c47-ae50267a7ca6.png)

2. SSH鍵の登録
githubの設定 (Settings) →　”SSH & GPG keys" →　”New SSH key"
Titleは自分で好きな名前をつけて、Keyには`id_github_rsa.pub`の内容を貼り付ける。

![settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/e6f13e30-9f49-4a39-01d9-41af697bafc4.png) 　　　　　![sshkey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/1ea68cba-f733-bba8-c234-59b2bcc8022a.png)
![sshkey2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/b71958e1-ea9c-1986-4b9d-9338617cb1f2.png)
![sshkey3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577966/34a37106-8a0f-6ec7-e392-3114958f14c9.png)

3.接続確認
`ssh -T git@github.com`コマンドで以下の表示が出ることを確認する。
```
% ssh -T git@github.com
Hi XXXXXX! You've successfully authenticated, but GitHub does not provide shell access.
```

3．gitクライアントの設定
(i)~/.ssh/configファイルの作成 (Userはgit. IdentityFileのファイル名は.pub無しとすること)
```
Host github
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_github_rsa
```

(ii)クローンしたフォルダに移動して
`git remote set-url origin github:ユーザ名/レポジトリ名.git`

(iii)試しにpushしてみる
```
% git push origin master
Everything up-to-date
```
errgroupのWithContextで得られるcontextは、局所的なcontextである

`errgroup.WithContext()`の返り値であるcontextは、非同期処理に対するcontextであり、それ以外の場所で使用してはいけない。
返り値のcontextを、それ以降の関数で使用すると、canceled contextなので不具合が発生する可能性がある。

`Wait()`した箇所で、contextがcanceledになる。それ以降の処理で使用しない方がいい。以下の様にするのがよさそう。
```go
// OK
eg, egCtx := errgroup.WithContext(ctx)

// NG
eg, ctx := errgroup.WithContext(ctx)
```

`eg, ctx := errgroup.WithContext(ctx)`だと、以下の様になってしまう。

```go
func main() {
	ctx := context.Background()
	fmt.Println(context.Cause(ctx) == nil) // true
	eg, ctx := errgroup.WithContext(ctx)
	fmt.Println(context.Cause(ctx) == nil) // true
	for i := 0; i < 10; i++ {
		eg.Go(func() error {
			return nil
		})
	}
	if err := eg.Wait(); err != nil {
		panic(err)
	}
	fmt.Println(
        context.Cause(ctx) == nil, // false
        errors.Is(context.Cause(ctx), context.Canceled), // true
    )
}
```
【初心者向け】CMakeLists.txtを使ってlibraryをリンクする。

# はじめに
[前回の記事](https://qiita.com/hi_to_san/items/00a5e9a75a8876b39492)からの続きになります。
今回はCMakeLists.txtを使ってlibraryファイルのリンクをしたいと思います。

# 参考サイト
* [かみのメモ](https://kamino.hatenablog.com/entry/cmake_tutorial1)
    * 1番読んだサイト
* [CMakeの使い方](https://qiita.com/shohirose/items/45fb49c6b429e8b204ac)
* [実践C++ 応用講座CMake編](https://theolizer.com/cpp-school3/cpp-school3-1/)

# 目次
* [まずはビルド](#まずはビルド)
* [記述内容の説明](#記述内容の説明)

## まずはビルド
### ファイルの準備
今回のディレクトリ構成は以下になります。
```
├── CMakeLists.txt
├── lib
│   ├── lib.cpp
│   └── lib.h
└── sampleApp.cpp
```
sampleApp.cppの他にlib.cpp, lib.hを用意しました。
lib.cpp, lib.hはlibフォルダに置いておきます。


今回のCMakeLists.txtの内容はこちらです。
```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(sampleApp CXX)

set(LIBRARY_NAME lib/lib.cpp)
add_library(library STATIC ${LIBRARY_NAME})

add_executable(sampleApp sampleApp.cpp)

target_link_libraries(sampleApp library)
target_include_directories(library INTERFACE ./lib)
```

<details>
    <summary>各実装は以下になります。（ここをクリック）</summary>

```c++:sampleApp.cpp
#include <iostream>
#include "lib.h"

int main(void)
{
    std::cout << "Hello,World" << std::endl;

    Library lib;
    std::cout << lib.lib_string() << std::endl;
}
```

```c++:lib.h
#pragma once

#include <iostream>
#include <string>

class Library {
public:
    std::string lib_string();
};
```

```c++:lib.cpp
#include "lib.h"

std::string Library::lib_string()
{
    return "library : Hello, World";
}
```
</details>


### ビルド
今回はmkdirでbuildディレクトリを作らずにcmakeで作成する。
```
cmake -Bbuild -H.
cmake --build build
```
これでbuildディレクトリにsampleAppが作られます。

### ファイル実行
```
$ ./sampleApp 
Hello,World
library : Hello, World
```
sampleApp.cppとlib.cppの文字が出力されます。

## 記述内容の説明
CMakeLists.txtに記述した内容について説明していきます。
```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(sampleApp CXX)

set(LIBRARY_NAME lib/lib.cpp)
add_library(library STATIC ${LIBRARY_NAME})

add_executable(sampleApp sampleApp.cpp)

target_link_libraries(sampleApp library)
target_include_directories(library INTERFACE ./lib)
```
今回は4行目から10行目までを解説します。
* 4行目：set(LIBRARY_NAME lib/lib.cpp)
    * `lib/lib.cpp` の値を`LIBRARY_NAME`に代入している。
    * 本来は複数の値を代入するが、今回は1つだけ。
* 5行目：add_library(library STATIC ${LIBRARY_NAME})
    * ライブラリファイルをビルドする。
    * `library`のライブラリファイル名を生成する。
    * `STATIC` 静的ファイルを生成する。
    * `${LIBRARY_NAME}` setで代入した値を指定してライブラリファイルにする。
* 7行目：add_executable(sampleApp sampleApp.cpp)
    * 実行ファイルを生成する。
* 9行目：target_link_libraries(sampleApp library)
    * `sampleApp` 実行ファイルに`library`ライブラリファイルをリンクする。
* 10行目：target_include_directories(library INTERFACE ./lib)
    * `./lib` ヘッダーファイルを`library `にリンクさせる。

# さいごに
以上で終了です。
ご参考になれば幸いです。

# 関連記事
* [【初心者向け】CMakeLists.txtを使ってビルドする。](https://qiita.com/hi_to_san/items/490f8320900617db9230)
* [【初心者向け】CMakeLists.txtを使ってincludeのpathを省略する。](https://qiita.com/hi_to_san/items/00a5e9a75a8876b39492)
* 【初心者向け】CMakeLists.txtを使ってlibraryをリンクする。
x軸に指定したカテゴリカルな値を平均値で並べ替える＆x軸にNAが入っている場合の対処（ggplot2）

# カテゴリカルな値をx軸に指定するとプロット時に困ることがある

たとえば以下のようなデータから箱ひげ図を作る場合

```r
library(tidyverse)

d <- tibble(
  id = 1:2000, 
  Group = rep(c("SS", "TT", "MM", "SW", NA), each = 400), 
  Value = {set.seed(1); lapply(1:5, rnorm, n = 400, sd = 1)} %>% unlist()
)

g <- ggplot(data = d, aes(x = Group, y = Value)) + 
  geom_boxplot()
ggsave(g, filename = "g.png")
```
![g.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535720/89de8009-84f1-c771-1330-3a1160129d83.png)


このように、
- x軸がアルファベット順になっているためわかりにくい
- NAの見栄えが悪い

という問題が生じる。この解決例。
もちろんデータフレームを整形してしまう方法もあるが、ここではプロット部分のコードで対応する方法を示す。

# x軸に指定したカテゴリカルな値を平均値で並べ替える：`forcats::fct_reorder`
![fct_reorder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535720/8b49792d-59fc-37df-74b1-c0be78489540.png)
> Source: Cheatsheets - Posit (https://posit.co/resources/cheatsheets/)

参考：[Reorder factor levels by sorting along another variable](https://forcats.tidyverse.org/reference/fct_reorder.html)

各カテゴリ内の値を特定の関数で要約し、その値をもとにカテゴリを並べ替えて因子の水準とします。
要約関数はデフォルトでは`median`なので、そのまま箱ひげ図の描画に使えます。

```r
g_reorder <- ggplot(data = d, aes(x = fct_reorder(Group, Value), y = Value)) + 
  geom_boxplot()
ggsave(g_reorder, filename = "g_reorder.png")
```
![g_reorder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535720/aa4ae561-c017-ed0f-e204-0fc8a3a0bc0e.png)

# x軸にNAが入っている場合の対処：`forcats::fct_explicit_na`
![fct_explicit_na.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535720/6d02557a-ba84-06bd-7a51-7edf0efabfb7.png)
> Source: Cheatsheets - Posit (https://posit.co/resources/cheatsheets/)

参考：[Make missing values explicit](https://forcats.tidyverse.org/reference/fct_explicit_na.html?q=_Na#null)

NAを含んだ文字列をそのまま`as.factor`してもNAに該当する列には水準が与えられませんが、`fct_explicit_na`を使用するとNAに対して特定の水準を与えることができます。
これを利用するとNAに該当する部分を最後尾にしたまま水準名を明示的なものに変更できます。

```r
g_explicit_na <- ggplot(data = d, aes(x = fct_explicit_na(Group, "UN"), y = Value)) + 
  geom_boxplot()
ggsave(g_explicit_na, filename = "g_explicit_na.png")
```
![g_explicit_na.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535720/d5c087c6-60c5-8390-3db2-6d2c52529ef5.png)

:::note info
forcats1.0.0では`fct_explicit_na`に代わって`fct_na_value_to_level`の使用が推奨されているそうです。
参考：[Convert between NA values and NA levels](https://forcats.tidyverse.org/reference/fct_na_value_to_level.html)
:::
「ITエンジニア採用“現状の壁”をどう突破するか？」参加レポート

2023/06/13、[ITエンジニア採用“現状の壁”をどう突破するか？](https://peatix.com/event/3591979)に参加しました。

## 株式会社grooves赤川 朗さん
自社サービス[Forkwell](https://forkwell.com/)に蓄積されたデータをもとに、転職市場の現状と取るべき採用戦略のお話をされていました。

### 転職活動にかける時間
まず、「ITエンジニアは転職活動にどのくらい時間をかけているか？」について。これは人によってまちまちではありますが、年収が上がるほど転職活動期間は長期化する傾向はあるようです。

### 年収
最近の求人トレンドとして、募集年収は年々上がっています。下限の年収は過去10年で170万円上がっています（ジュニアレベルのエンジニアに要求されているレベルが特別上がってるわけではないのに関わらず）。
ただ、今は年収の上昇は一旦踊り場に来ているかもしれないとのことです。このお話は赤川さんが先日公開された[本当にエンジニアバブルは崩壊したのか？](https://pr.forkwell.com/articles/has-the-engineering-bubble-about-to-burst/)に詳しく書かれているので、こちらもチェックしてみてはいかがでしょうか。

### 職種の種類
募集する職種の種類は近年増えていて（EM。SRE、データエンジニアなどが登場）、分業化が進んでいる印象があります。

### 使っているプログラミング言語
使っているプログラミング言語は年々多様化しています。自社が選択した技術はこの先どうなりそうかを考える必要がありそうです。

### リモートワーク
フルリモート率は50％超え。一部リモート対応まで含めると95％がリモートワークということで、リモートワークを許可するかどうかは採用戦略を考える上で重要な要素になりそうです。

### プログラミング言語と年収に相関関係はあるか？
よく言われる都市伝説（？）として「このプログラミング言語を使えると年収が高い」といった話を聞くことがありますが、プログラミング言語と年収の関連についてのデータも見せていただきました。
プログラミング言語ごとの年収の差はデータを出すと一見相関関係があるように見えますが、その言語の市場価値と捉えないほうがいいとのことです。言語ごとに利用している人口は違うので、その差が影響を与えているのではないかとのことです。

### 自社で転職したほうが給料が上がる？
これまた都市伝説的な話ですが、転職回数と平均年収の関係をデータで見ると、20代、30代は転職回数が多いと年収が増える傾向があるものの、40代では大きな差は見られないそうです。
これは、同じ役割でも所属する業界によって給料の中央値が大きく異なることが原因ではないかと分析されていました。

### 採用戦略をどうするべきか
まず、採用した人にやってもらいたい役割に応じて給与レンジを決めるするのが重要。
メガベンチャーや外資出身の人であれば給与レンジは高い傾向にあるので、自社を最初から選択肢に入れてもらえない可能性があります。
自分たちが狙えるのはどの層の人たちか、よく見極めて戦略を練る必要がある、とのことでした。

## Attack株式会社 村上 篤志さん
より採用時にどういうアプローチを取れば求職者の反応を得られやすいのか、というお話をされていました。

採用人数は以下3つの掛け算で決まります。

- 採用チャネル数（e.g. スカウトメディア、エージェント、リファラル、直接エントリー）
- チャネルごとの候補者数
- 選考通過率

「採用チャネル数」は基本的に複数のメディアを利用するのがよい。
特にダイレクトリクルーティングはコストメリットが高いので活用するべきとのことです。
ただしダイレクトリクルーティングは利用企業の業務負荷が高くなる傾向があるので、運用体制をしっかり整えることが重要とのことでした。

スカウトメールの返信率を上げるための分析ポイントは以下の３つ。
- 開封率（既読率）
- 閲覧率
- 応募率

エンジニアの転職理由は以下の通り。これを意識してスカウトメールの文面を考えるとよいとのことです。

- 給料
- 成長
- 人間関係
- 貢献

候補者の経歴やスカウト理由を書くなどして作り込まなくてもOK。エンジニアは対象のメールを受け取るので、簡潔に自社の魅力を伝える文面のほうが返信率が高いとも話されていました。
確かに最近はスカウトメールの類は目にする機会が増えてきたので、個人的にもそんなに時間をかけて読まなくなった気がします。
DockerでPlaywrightを起動する。

## PlaywrightでDockerを動かす

### JSで作る
```shell:ディレクトリ構成
~/develop/docker/playwright_docker$ tree
.
├── Dockerfile
└── script.js

1 directory, 2 files
```

```dockerfile:Dockerfile
# ベースとなるDockerイメージを指定
FROM mcr.microsoft.com/playwright:focal

# ワーキングディレクトリを設定
WORKDIR /app

# 必要なパッケージをインストール
RUN npm init -y
RUN npm install playwright

# スクリプトをコピー
COPY script.js /app/script.js

# コンテナ起動時に実行するコマンドを設定
CMD ["node", "script.js"]

```

```js:script.js
const { chromium } = require('playwright');

(async () => {
//   const browser = await chromium.launch({headless: false});
  const browser = await chromium.launch({headless: true});
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://www.google.com');
  const title = await page.title();
  console.log(title);
  await browser.close();
})();

```

```shell:イメージ作成
docker build -t my-playwright-app .
```

```shell:実行結果
~/develop/docker/playwright_docker$ docker run my-playwright-app       
Google
```

### TypeScriptで作る

```dockerfile:Dockerfile
# ベースとなるDockerイメージを指定
FROM mcr.microsoft.com/playwright:focal

# ワーキングディレクトリを設定
WORKDIR /app

# 必要なパッケージをインストール
RUN npm init -y
RUN npm install playwright typescript ts-node

# スクリプトをコピー
COPY script.ts /app/script.ts

# コンテナ起動時に実行するコマンドを設定
CMD ["npx", "ts-node", "script.ts"]

```

```ts:script.ts
import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch({ headless: true });
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://www.google.com');
  const title = await page.title();
  console.log(title);
  await browser.close();
})();
```

→GUIを表示するのは追加で設定が必要なようだ。
Laravelでデータの変更履歴用トレイトをつくる

**内容**：Laravelでデータの変更箇所を追跡する方法です。

**なぜ書いたか**：現場で変更履歴を表示させる処理が必要になったから。備忘録です。
[Laravel Auditing](https://laravel-auditing.com/)というパッケージもありますが、今回はトレイトの作成にしました。

※記事では各ファイル作成コマンドの記載は省きます。
コマンドの一覧は[こちらの記事](https://qiita.com/ryocha12/items/2c15ad2377c36dfcf408)をご参考ください！

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

**① 履歴変更保存用のテーブルをデータベースに作成する**
- 話のメインになる項目は下記3つ。
     - カラム名を取得する'column_name'
     - 古い値を取得する'old_value'
     - 新しい値を取得する'new_value'
      

**②  モデルの作成**
 ```php:ChangedHisotry.php モデルです
//namespaceとかuseとか
class ChangedHistory extends Model
{   
    protected $table = 'changed_history'; //テーブル名

    protected $fillable = [
        'id',
        'column_name',
        'old_value',
        'new_value',
        'created_at',
    ];
}
```
こんな感じです。


**③ トレイトの作成**
- \app\Traitsに作成。この場合はHasChangedHistory.phpにします。
``` php:HasChangedHistory.php トレイトです
//namespaceとかuseとか
trait HasChangedHistory
{
    public static function bootHasChangedHistory()
    {
        //updatedの時に動作する
        static::updated(function ($model) {
            //トレイト内の処理()を指定しています。
            $model->recordChangedHistory('updated');
        });
        /*createdやdeletedでも動作させたい場合は

            static::created(function ($model){
                このように追記
            });        
       
         */
    }

    public function recordChangedHistory($event)
    {   //DBの差分を取得するメソッドgetChanges()
        $changedAttributes = $this->getChanges(); 
        //連想配列を処理する
        foreach ($changedAttributes as $column_name => $newValue) {
            //変更前の値を取得するメソッドgetOriginal()
            $oldValue = $this->getOriginal($column_name);
            $changeHistory = \ChangedHistory::create([
                'id' => $this->id,
                'column_name' => $column_name,
                'old_value' => $oldValue,
                'new_value' => $newValue,
            ]);
        }
    }   
}

```

**④ 変更を追跡したいモデルに追記する**
```php:FooModel.php 変更を追跡したいテーブルのモデルです
//色々なuse
use App\Traits\HasChangedHistory; //こちら！！！

class Foo extends Model
{
    //色々なuse
    use HasChangedHistory; //こちら！！！
```
上記設定をして、対象テーブルを変更するとchanged_historyテーブルに行が追加されているかと思います。

**おわり**



-------------------------------------
**参考にした記事**
- [DBの変更履歴の作成(全４ページあります)]( https://www.larajapan.com/2020/05/24/db%e5%a4%89%e6%9b%b4%e5%b1%a5%e6%ad%b4%e3%81%ae%e4%bd%9c%e6%88%90%ef%bc%88%ef%bc%92%ef%bc%89%e7%9b%a3%e6%9f%bb%e3%81%ae%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e4%bf%9d%e5%ad%98/ )

- [【Laravel】追加・変更・削除・閲覧した人の履歴を自動で保存する](https://blog.capilano-fw.com/?p=8622)

また、初めてQiitaに投稿するので下記にも大変力をいただきました！ :tiger: 
- [Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
MATLAB uifigureを使ったGUIアプリの作成例

MATLABにはGUIアプリを作る方法がいくつかあります．

1. App DesignerというGUIアプリケーションを使って作る
1. コードを書いて作る

ここでは2. の方法で作ってみます．MATLABにもGUIを作るフレームワークがあります．
GUIフレームワークにも様々とパラダイムがありますが，MATLABのはPythonのtkinterと似ていると思います．

### ウィンドウを作成する `uifigure`
```matlab
fig = uifigure;
fig.Name = "MATLAB GUI Test";
```
こんだけで白いウィンドウが立ち上がります．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/d0e5f671-1094-4acd-2203-ecb9678503e3.png)

### レイアウトを設定する `uigridlayout`
引数に親コンテナを指定します．なんかtkinterと似ていますね．
```matlab
layout = uigridlayout(fig,[2 2]);
```

### ラベルを作成する `uilabel`
親コンテナとしてレイアウトを指定すると，レイアウトに従って適当な場所に配置されます．
```matlab
greeting_label = uilabel(layout);
greeting_label.Text = "お帰りなさい，あなた．何にする？";
greeting_label.HorizontalAlignment = "right";
```
![スクリーンショット 2023-06-13 21.39.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/56620062-0899-7e3a-6941-63afa6288f54.png)

### ドロップダウンを作成する `uidropdown`
```matlab
dropdown = uidropdown(layout);
dropdown.Items=["ごはん","お風呂","ワ・タ・シ♡"];
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/ad272fa2-081c-b9d6-4a31-c791388cd884.png)

### グリッドの複数行・複数列に渡るレイアウト
今から下行に2列に渡ってラベルを配置したいと思うのですが，そういう時はコンポーネントの`Layout`プロパティから変更ができます．例えば以下の例では1から2列目に渡ることができます．
```matlab
reaction_label = uilabel(layout);
reaction_label.Text = "";
reaction_label.HorizontalAlignment = "center";
reaction_label.FontSize = 32;
reaction_label.Layout.Column = [1 2];%1から2列目に渡る．
```
### イベントハンドリング
ここでは，ドロップダウンの選択内容に従ってラベルの文字列を変更させるようにします．

イベントハンドラは以下のような2つの引数を受け取る関数として定義されます．`src`にイベントの発信元のコンポーネントが入ります．
```matlab:イベントハンドラの関数
function handler(src,event)
```
このようなイベントハンドラを作って，当該のコンポーネントのプロパティに登録します．

ドロップダウンの選択ハンドラは`ValueChangedFcn`プロパティに登録します．
```matlab
    function on_select(src,event)
        SELECTION_TO_REACTION = dictionary( ...
            "ごはん","⊂((・⊥・))⊃", ...
            "お風呂","(*ﾟ▽ﾟ)ﾉ", ...
            "ワ・タ・シ♡","/////////" ...
        );
        reaction_text = SELECTION_TO_REACTION(src.Value);
        reaction_label.Text = reaction_text;
    end
dropdown.ValueChangedFcn = @on_select;
```
### 動作例
「ごはん」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/1f49c5e0-c623-55bb-ad7b-0ea5c20b6fcc.png)
「お風呂」を選択すると，下部のラベルの内容が変わります．
![スクリーンショット 2023-06-13 22.01.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/6e501e7e-2e20-3a2d-6bdd-d4b1e4431bf1.png)

### まとめ
以上で作ったコードをまとめます．ここでは1つの関数として包んでいます．

https://gist.github.com/Mya-Mya/2a5170881b2750a42a1972593f4113d7

MATLABのGUIフレームワークについて，詳細は↓のドキュメントにアクセスして下さい．

https://jp.mathworks.com/help/matlab/develop-apps-using-the-uifigure-function.html

いやあ，MATLABは何でもできますねえ...卒業しても離れられる自信がない．
承認プロセスって意外にわかりづらい

## はじめに
Salesforceの「承認プロセス」機能とは、業務上の申請業務を効率化するツールのことです。
勉強していく中で意外と理解しづらい点が多いと思ったため、その機能を簡潔にまとめていきます。

## 承認プロセスとは
「承認プロセス」とは、その名の通り、許可を取りたい人が申請を行い、許可権限を持つ承認者がその申請を承認する一連の流れのこと。
Salesforceを活用することで、一例として以下のことが可能。
- 交通費申請は経理部の担当者、有給休暇申請は部署内の上長に申請する。
- 承認完了や過去の承認記録を、レコード詳細画面上に一覧表示する。
- 承認や却下の際に自動で実行する追加アクション（項目自動更新、メール送信など）を設定する。

[参照：Salesforce ヘルプ「承認プロセスの設定」](URL "https://help.salesforce.com/s/articleView?id=sf.approvals_getting_started.htm&type=5")

## 承認プロセス設定の流れ
### 事前の準備
承認プロセスを設定する前に、以下のことを準備する。
- 承認プロセスの対象となる標準・カスタムオブジェクトを作成する。併せて、承認プロセス上で使用したい項目（自動更新したい項目、承認プロセスの起動時の検索条件として使用したい項目など）を設定する。
- ユーザオブジェクトに対して、上記と同様に承認プロセス上で使用したい項目を設定する。
    - ユーザには、マネージャや代理承認者を設定することが可能であるが、実案件ではあまり使用されないイメージ。

### 承認プロセスの作成
以下の流れで、承認プロセスを設定していく。
1. 設定/承認プロセスを選択する。「承認プロセスを管理するオブジェクト」から対象とするオブジェクトを選択し、「承認プロセスを新規作成」を押下する。
    - このとき、「ジャンプスタートウィザード」か「標準ウィザード」の2種類の設定方法があるが、2つの設定方法にそこまで大きさ差異がない。「標準ウィザード」のほうがより複雑な設定が可能。
2. Salesforceの画面を通じて、以下を設定していく。
ここでは、一つの承認プロセス全体の設定をまとめていく。
    - プロセス名と一意の名前
    - 承認プロセスの開始条件（現在のユーザ、該当オブジェクトの項目を検索条件とする）
    - 割り当て先として使用するユーザ項目、編集権限のプロパティ
    - 承認申請が割り当てられたことを承認者に通知するメールテンプレート
    - 承認者が実際に申請を承認・却下するページに表示する項目
    - 承認申請を実行できるユーザ
3. 承認ステップを追加する。
前項で作成した承認プロセス詳細画面に対して、承認ステップを追加していく。実務に沿って、承認申請を複数のステップを通じて設定していく。
具体的には以下を設定する。
    - プロセス名、一意の名前、順番
    - 承認ステップの割り当て先（手動で選択、キューに割り当てる、自動で割り当てるなど）
    - 各承認ステップの「承認時のアクション」と「却下時のアクション」
        - 各アクションはメールアラート、項目自動更新、アウトバウンドメッセージから設定できる。
4. 最終承認時、最終却下時、取り消し時のアクションを設定する。
   - 各アクションの定義は下記の通り。
       - 最終承認：レコードが必要な承認をすべて受けた後に実行。
           - たとえば、最終承認時のアクションにより、レコードの状況を「承認済み」に変更したり、メール通知を送信したりすることができる。
       - 最終却下：レコードが承認プロセスから完全に却下されたときに実行。
           - たとえば、最終却下時のアクションにより、レコードの状況を「却下済み」に変更したり、メール通知を送信したり、レコードのロックを解除したりすることができる。
       - 取り消し：送信された承認申請が取り消された場合に、取り消しアクションが実行。
           - たとえば、取り消しアクションにより、レコードの状況が「処理中」から「未申請」に変更される。
4. 承認プロセスを有効化する。
   最後に、設定画面上から承認プロセスを「有効化」する。必要に応じて、「承認履歴」コンポーネントをレコード詳細画面上に表示する。
react+express(docker)環境構築での問題

# 問題内容

reactコンテナからexpressコンテナに向けてコンテナ間通信しようと思ったら、なぜか名前解決できないと言われた。

# 背景

コンテナでreactとexpressの開発環境を構築。

ディレクトリ構造は以下。

app_name/
　┣client/
　┃　┣dockerfile
　┃　┗app/(react)
　┣server/
　┃　┣dockerfile
　┃　┗app/(Express)
　┗docker-compose.yaml
```docker-compose.yaml
version: "3"
services:
  client:
    build: ./client
    container_name: client
    hostname: client
    environment:
      - NODE_ENV=DEVELOPMENT
      - PORT=3000
    volumes:
      - ./client/app:/usr/src/app
    ports:
      - 3000:3000
    working_dir: /usr/src/app
    command: sh -c "npm start"
  server:
    build: ./server
    container_name: server
    hostname: server
    environment:
      - NODE_ENV=DEVELOPMENT
      - PORT=3001
    volumes:
      - ./server/app:/usr/src/app
    ports:
      - 3001:3001
    working_dir: /usr/src/app
    command: sh -c "npm install -g nodemon && nodemon index.js"
```
composeファイルにcmdやらを全て書いている。

ローカルのディレクトリとコンテナのディレクトリを共有するように書いている。

これは、ローカルでコードを更新してもそれがコンテナ内で反映されるようにバインドマウントを採用している。

reactの場合、ホットリロードするためにはpackage.jsonにちょっと書き加えないといけない。
```package.json
"scripts": {
    "start": "WATCHPACK_POLLING=true react-scripts start",
```
# 本題

reactコンテナからexpressコンテナに向けてコンテナ間通信しようと思い、

http\://server:3001/apiみたいな感じでgetやpostしに行ったら

net::ERR_NAME_NOT_RESOLVEDというエラーが出て名前解決されないと出た。

記憶では同じネットワークにあるコンテナ同士はコンテナ名で通信するんじゃなかったっけな、

と思い調べるとそれで合っていた。

だけど名前解決されず通信されないのはなぜ？と思い調べると、

reactは**ブラウザ上で動くためコンテナ内で動くことはない**、よってコンテナ間通信と思わないで

ローカル→コンテナ間通信のようにhttp\://localhost:3001/apiでやらないといけないとのこと。

バックエンドとDB、両方コンテナで行った場合、バックエンドとDB間のコンテナ間通信は

バックエンドはコンテナ内で動くため先ほどのコンテナ名を使ったやり方でOK。

めちゃくちゃ当たり前だけど、分かったとき感動した。

# 参考

https://qiita.com/Mayumi_Pythonista/items/11b412e59e045a2c5eb3
PowerAutomate: OfficeScript(*.osts)がOneDrive以外における＝共有できる。2023/6/6 ぐらい～

# 背景
新しい業務準備の為に Power Automate を久し振りに触っていたら、色々と知らない Action とかが見つかったので、その備忘録の一つ。

一番の価値は
- officeScripts の置き場所が選べるようになったことで、共有しやすくなった事である。

以前は、\<OneDrive/Documents/Office Scripts>  にしか保存できなかったので。

ただ、課題としては
- Excel も不要にしてくれ・・

理由は
- Office Scripts は、Excel専用じゃない（筈）
- Excel 以外の自動化にも利用する場合に、今回の例のように Dummy Excel を指定する必要がある

# 二つの Action
- :new: [Run script from SharePoint library (preview) (Preview)](https://learn.microsoft.com/en-us/connectors/excelonlinebusiness/#run-script-from-sharepoint-library-(preview)-(preview))
- [Run script](https://learn.microsoft.com/en-us/connectors/excelonlinebusiness/#run-script)

現時点でもまだ日本語ドキュメントは無いんですが・・ :laughing: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/22ce4497-86d5-d8ff-157e-78322435a066.png)

# 実際に使ってみた例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/bcfdc8e6-b54b-c8fe-48a0-4405508a0dca.png)

利用した例は、以下のやつ

https://qiita.com/baku2san/items/74885b03ada5be8f6f42

# そもそも Office Scripts って？
以下にあるように、End-user 用のWeb での自動化。言ってみれば、Web版VBA みたいなもの

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/78f338ce-b9ac-1cb0-da9f-c6946e8992b5.png)

https://learn.microsoft.com/ja-jp/office/dev/scripts/resources/vba-differences

# あとがき

そのうち他のOfficeでも使えるようになって、
Excel ファイルの指定が要らなくなることに期待
※恐らく、Script Engine 用にExcel を指定しているのが現状なので・・

ただ、以下・・ずーっと Excel 主体というか、のみ、なんですけどねぇ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/4398e22d-a6c0-9692-9777-240c64a74438.png)

https://learn.microsoft.com/en-us/office/dev/scripts/?view=office-scripts
ラズパイ4台のk3s環境整えた

# 環境
デバイス: Raspberry Pi 4 Model B Rev 1.2　(RAM 4GB)
デバイス: Raspberry Pi 3 Model B Rev 1.2　(RAM 1GB) * 3台
計 4台

OS: Ubuntu 22.04

私は、4台のラズパイのマシン名を次のように命名しました。
- k3s0
- k3s1
- k3s2
- k3s3

4Bをserverとして、3B * 3をagentとして動かしていきます。
3Bをserverとして動かしてみましたが、さすがに性能面で厳しそうでした。

# 手順

使用するラズパイ4台で、以下の準備をしておきます。
- いつもの`sudo apt update && sudo apt full-upgrade -y && sudo apt autoremove -y`。
- ラズパイに固定IPアドレスを振ります。(私は、ルータのDHCP設定でやりました。`/etc/netplan/99_config.yaml`で指定する方法もあります。)
- SSHでそれぞれのラズパイにアクセスできるようにしておきます。
- `hostnamectl set-hostname [hostname]`でマシン名をk3s0、k3s1、k3s2、k3s3と設定します。(`/etc/hostname`を直接書き換える方法もあります。)
- `/etc/hosts`を編集します。
```:/etc/hostsの例
・・・

192.168.10.110  k3s0
192.168.10.111  k3s1
192.168.10.112  k3s2
192.168.10.113  k3s3
```
- cgroupのmemoryを有効化します。
```bash: コマンド
echo 'cgroup_memory=1 cgroup_enable=memory' | sudo tee -a /boot/firmware/cmdline.txt
sudo reboot

# ↓変更後の /boot/firmware/cmdline.txt
# console=serial0,115200 dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash
# cgroup_memory=1 cgroup_enable=memory
```
- ラズパイでCNIを使えるように、モジュールをインストールしてカーネルをアップデートします。
```bash: コマンド
uname -r
# 5.15.0-1030-raspi より前のバージョンなら
# カーネルをアップデートする必要があります。

sudo apt install -y linux-image-5.15.0-1030-raspi linux-modules-extra-raspi && reboot
# 再起動が終わったら、uname -r コマンドでカーネルのバージョンを確認します。
```

## K3s server
```bash: コマンド
curl -sfL https://get.k3s.io | sh -

# .kube/configを作成して、ユーザからk3sコマンドを叩けるようにします。
mkdir -p ~/.kube
sudo k3s kubectl config view --raw | tee ~/.kube/config
chmod 600 ~/.kube/config

# bashを使用しているので、~/.bashrc に環境変数を定義します。
echo "export KUBECONFIG=$HOME/.kube/config" >> ~/.bashrc

# 後で使います。
sudo cat /var/lib/rancher/k3s/server/node-token
# 出力されたものがトークンです。
```

## K3s agent
```bash: コマンド
# [k3s server address]と[token]はそれぞれ置き換えてください。
curl -sfL https://get.k3s.io | K3S_URL=https://[k3s server address]:6443 K3S_TOKEN=[token] sh -

# ↓私の環境ではこんな感じ
curl -sfL https://get.k3s.io | K3S_URL=https://k3s0:6443 K3S_TOKEN=K10637d9f854b81c23f736271bc3cd82a15e96995708bb410c291217c53c006f099::server:ee9a79baaa98dbe0b420f27928432af7 sh -
```

## 確認
```
k3s kubectl get node
# ↓こんな感じで出力されます
# NAME   STATUS   ROLES                  AGE   VERSION
# k3s1   Ready    <none>                 46h   v1.26.5+k3s1
# k3s2   Ready    <none>                 46h   v1.26.5+k3s1
# k3s3   Ready    <none>                 46h   v1.26.5+k3s1
# k3s0   Ready    control-plane,master   46h   v1.26.5+k3s1
```

# 最後に
Ubuntuインストールしたラズパイ（特にラズパイ3）を使っていたのが原因で、CNI周りで結構沼りました。。。
楽しいk3sライフを。
【Xcode】「< Back」がダサいと思って「<」に変更したい場合【UI/UX】

以下の画像の「CommnetViewController」の「< Back」を「<」に変えたい場合
親に該当する「CheckViewController」の「< Back」 辺りをタップします。

![スクリーンショット 2023-06-13 21.41.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/9814594b-eade-98fd-0548-98af8435fc41.png)

すると、以下の画像の「Navigation Item」の「Back Button」が見えます。

![スクリーンショット 2023-06-13 21.44.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/b752e173-6d17-35a4-68c4-88ee49d1d936.png)

その「Back Button」にカーソルを持っていき、半角スペースを開けて「Enter」をすると、、、

![スクリーンショット 2023-06-13 21.48.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/affbb53d-026e-bf08-b648-7970004f6496.png)

「< Back」を「<」に変更することに成功しました。

# 参考教材
【iOS14対応】未経験者がiPhoneアプリ開発者になるための全て iOS Boot Camp
406. ログアウト機能を簡単に作成しよう！
Reactで作成したブラウザアプリをサーバーに置くのに苦労した話

# このポスト
初めて、Reactでブラウザアプリを作成し、ローカルでの一通りの機能を試し、いざサーバーに置こうとしたら苦労した話。

### 問題の始まり
プロジェクトを置いてあるフォルダで、
npm run build
を実行し、buildフォルダ内に作成されたファイル群を、サーバー上の公開用のフォルダに置いた。でもアクセスしても画面は真っ白。

### 問題の解決方法: .htaccessファイルの編集
いくつかのページを見ると、サーバーの.htaccessファイルの編集と、build前にpackage.jsonファイルの編集が必要だとのこと。
.htaccessファイルは

```apache
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /TraceViewer/
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-l
    RewriteRule . /TraceViewer/index.html [L]
</IfModule>
```
とした。これはchat GPTの言うなり。

### 問題の解決方法: package.jsonファイルの編集
package.jsonファイルには、
"homepage": "https://serverDomainName/TraceViewer"
のように付け加えろとのこと。

Visual Studio Codeでpackage.jsonファイルを編集、そして保存のためにコマンド+S(ここ！)。buildして得られたファイルをアップロード。しかし、ブラウザでアクセスしても画面は真っ白のまま。

悪戯に時が流れていく。とその時、package.jsonファイルをテキストエディットで開いてみたら、"homepage":の行がない！ちゃんと保存したはずなのに、保存されていない。

調べてみると、ファイルの所有者がシステムになっており、保存できていなかった。Visual Studio Codeではこのようなときにエラーメッセージは出ないらしい。
以下のようにして、ファイルの所有者を変更。

```bash
sudo chown [ユーザー名]:[グループ名] package.json
```

なお自分のユーザー名とグループ名は、
```bash
id -un
id -gn
```で調べられるとのこと。

これで所有者を変更。そして権限を変更。
```bash
chmod 755 filename
```

このあと再度
```
run npm build
```
してファイルをアップロード。無事に表示されました。

### 教訓
ファイルはちゃんと保存できたか確認しましょう。
Visual Studio Codeでは、ファイルタブの右端に白丸が表示(↓)されている時は保存されていません。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595771/b6a0ce14-d250-7d11-0d4d-bbcdfd9a7ac7.png)
コードの写経やってみてわかったこと

最近Webデザイン系の書籍に書いているソースを写経しながら勉強しています。
今までは読んで、自分が知らなかったところをメモするぐらいだったのですが、写経してみてこれいいなと改めて思ったのでその理由について紹介していきます。

## 開発環境について考えるようになる
だいたいの書籍では実際に手で書いて動かせるように開発環境の作り方の説明がされています。
ただそこに書いている内容だけだと効率的にソースが書けないことが多いです。
特に古い本だとIntelliJではなくEclipseだったり、VSCodeじゃないものを使っていたりします。

そこで自分が使いたいIDEを使うようになって、さらにプラグインやViteなどを使ったライブコーディングでより効率的に開発することを考えるようになります。

私は基本的にライブコーディングと自動フォーマットは欠かせないので、ViteとPrettierを入れて今はフロント系のサンプルソースの写経を行っています。また、Emmetを使ってより早くコーディングしています。

写経に合間にプラグインやIDEの設定を調べて、もっと効率的にと考えるようになりました。

## 書籍に書かれていること以上のことが学べる
開発環境もそうなのですが、実際にソースを書いていると書籍に書いていないことも考えるようになり、書籍の内容以上のことが学べます。

例えば、書籍ではCSSで書いていても、自分はSaasを使ってモジュール分割して書いていたりします。
サンプルソースだけだとステップ数は少ないので、CSSでも大丈夫なんですが、個人的には細かく分けたいんですよね。
あとはこのやり方だとSaasを始めるのにやさしくて初心者にとってもいいなと思いました。
ソースのステップ数が少ないということはそれだけ考えることは少ないので、Saasのやり始めにはちょうどいいです。

## 写経にはこんなやり方も！
今日ネット記事をいろいろ見ていて、これいいな！と思ったのが進捗をGitで管理するということです。
これならコミット履歴を毎日欠かさずつけることで、サボり防止にもなりますし、後で見たときに達成感があると思います。

それにGitの知識もつけられますし、毎日コーディングする日課にもなりそうです！
私も今日からGitで進捗管理していこうと思います！

## まとめ
「プログラミングは書いて覚える」というのは昔から言われていることですが、仕事が終わって家に帰ってからやってると中々時間がありませんよね。

特に実際に書きながらやってると時間があっという間に過ぎていきます。

ただ最近本の写経から始めてみて思ったのが、やっぱりプログラミングって楽しい！ってことです。
読んでるだけだと頭に入らなくて、読むのと書くのでは全然違うな！って改めて思いました。
Django学習備忘録 -models.pyで作成したDBへの保存方法-

# はじめに
Djangoの私的学習メモです。
ChatGPTにて調べた内容と追加で調べた内容を見返せるように記事としてまとめました。
情報の裏取りはしていないので間違いがありましたらご指摘いただけると幸いです。


## データベースへの保存方法
大きく分けて2種類の方法がある。
Djangoモデルを経由して保存する方法と経由しない方法である。
Djangoモデルを経由しない方法はPythonの標準的なデータベースAPIを使用することで実装できる。
これにはPythonのsqlite3モジュールや、MySQLやPostgreSQLにアクセスするためのpsycopg2やmysql-connector-pythonなどがあるがここでは割愛する。

## Djangoモデルを使用するメリット
Djangoはデータベースとのインタラクションを抽象化するためのORM（Object-Relational Mapping）を提供しています。これは、アプリケーションが使用するデータベースに関係なく、Pythonコードでデータベース操作を行うことを可能にします。

つまり、SQLiteを使用していても、MySQLを使用していても、PostgreSQLを使用していても、同じDjangoモデルのコード（例えばsaveメソッドやobjects.createメソッドなど）を使用してデータベースにデータを保存することができます。

そのため、データベースエンジンを変更する場合でも、ほとんどの場合、Pythonコードを変更する必要はありません。ただし、Djangoの設定でデータベースエンジンの設定を変更する必要はあります。

## adminページから保存する
adminページからデータを記入し保存することができます。
よくブログサイトを作る例とか取り上げられているやつです。
詳細はリンク先を見てください。

https://qiita.com/Bashi50/items/280bc341eeec5d7f8797


## インスタンスを作成した後saveメソッドで保存する
Djangoモデルを使用してデータベースにデータを保存する基本的な方法は、新しいモデルのインスタンスを作成し、その`save`メソッドを呼び出すことです。

1. **モデルインスタンスの作成：**
    あるモデル`Person`があるとしましょう。新しいインスタンスを作成するには以下のようにします：

    ```python:my_app.py
    from myapp.models import Person

    person = Person(name="John Doe", age=25)
    ```

2. **インスタンスの保存：**
    モデルインスタンスを作成したら、そのインスタンスをデータベースに保存するには`save`メソッドを呼び出します：

    ```python:my_app.py
    person.save()
    ```

これで、新しい`Person`インスタンスがデータベースに保存されます。なお、すでに存在するインスタンスのフィールドを更新する場合も`save`メソッドを使用します。


## 複数のデータをbulk_createメソッドで一度に保存する
一度に複数のモデルインスタンスをデータベースに保存する場合は`bulk_create`メソッドを使用することができます。

```python:my_app.py
from myapp.models import Person

people = [
    Person(name="John Doe", age=25),
    Person(name="Jane Doe", age=30),
    # ...
]
Person.objects.bulk_create(people)
```

このメソッドは一度に多数のレコードをデータベースに保存するための効率的な方法です。

個人的にはpandasのDataFrameをデータベースに保存するときに使っています。

```python:my_app.py
def save_df_to_database(df):
    persons = [
        Person(
            first_name=row['first_name'],
            last_name=row['last_name'],
            birth_date=row['birth_date'],
        )
        for index, row in df.iterrows()
    ]
    Person.objects.bulk_create(persons)
```

dfからデータを1行ずつ取り出しインスタンスを作成、作成したインスタンスをリストに格納し、最後に一括でデータベースに保存しています。

## createメソッドでインスタンスの作成と保存を一度に行う
モデルには`create`メソッドもあり、これを使うとモデルインスタンスの作成と保存を一度に行うことができます：

```python:my_app.py
person = Person.objects.create(name="John Doe", age=25)
```

インスタンスを作成したあとデータの加工をする必要が無い場合にsaveメソッドを使うよりコードの省略できます。

## まとめ

Djangoモデルを使用することで使用するデータベースによることなく一律の記載で保存をすることができます。
**インスタンスを作成そのまま保存したい場合は"createメソッド"** を 
**インスタンスを作成し加工等処理を行なった場合は"saveメソッド"** を 
**複数のデータを一括で保存したい場合は"bulk_createメソッド"** を使用する。
ALL Google Cloudで構成しようとしたけど、色々と更新停止しているサービスがあったよ

## Google Cloudの以下のサービスはメンテナンスが止まっている
・[Cloud Source Repositories(Google Cloudのソースコードリポジトリ)のリリースノート](https://cloud.google.com/source-repositories/docs/release-notes?hl=ja)
→2018 年 8 月 8 日でアップデートがストップ

・[Deployment Manager(Google Cloudの構成管理、IaCツール)のリリースノート](https://cloud.google.com/deployment-manager/docs/release-notes)
→2020 年 4 月 15 日でアップデートがストップ

## 代替策
・Cloud Source Repositories
以下のサイトを見ると、Cloud Build(GoogleのCIツール)の最新世代ではGitHubとGitHub Enterpriseのみプロバイダとして対応しているとのことで、GitHubの利用が代替策と思われる。

https://cloud.google.com/build/docs/repositories?hl=ja#repositories_2nd_gen

・Deployment Manager
公式サイトに「Google Cloud での Terraform」というページがあり、Terraform利用が代替策と思われる。
※そもそもマルチクラウドで利用できるIaCツールの選択肢的にもTerraform以外が思いつかない。

https://cloud.google.com/docs/terraform/get-started-with-terraform?hl=ja

## まとめ?
以下の記事で紹介されているように、Google Cloud自体が他のクラウド(AWS,Azure)と組み合わせて利用してもらう戦略をとっているらしい(Googleは得意なデータ分析領域で利用してもらう形)。

https://monoist.itmedia.co.jp/mn/articles/2204/07/news056.html

そのため、マルチクラウドでの利用が前提になるかなと予測はしていたが、GitHubやTerraform等含めると思っていた以上に他社サービス(もしくはSaaS)と一緒に利用することになりそうである。

AWSのようにCodeシリーズやCloudFormation等細かいところでも一社完結できるというのは、結構すごい(ありがたい)ことなのだなと再認識した。