OmniAICreator/Qiita-1.07M huggingface dataset:
【Atcoder】M - Candies【DPまとめコンテスト】

# 問題
https://atcoder.jp/contests/dp/tasks/dp_m

# 結論
dp[i][j] := i人目まででj個ぴったり配る場合の数

```python
def getInts():
    return map(int, input().split())


def getIntsArray():
    return [int(x) for x in input().split()]


N, K = getInts()
Capacities = getIntsArray()
MOD = pow(10, 9) + 7

dp = [[0] * (K + 1) for _ in range(N + 1)]
dp[0][0] = 1
for i in range(1, N + 1):
    cumsum = [0] * (K + 1)
    cumsum[0] = dp[i - 1][0]
    for k in range(1, K + 1):
        cumsum[k] = cumsum[k - 1] + dp[i - 1][k]
        cumsum[k] %= MOD
    for k in range(K + 1):
        capacity = Capacities[i - 1]
        min_limit = k - capacity - 1
        if min_limit >= 0:
            dp[i][k] = (cumsum[k] - cumsum[min_limit]) % MOD
        else:
            dp[i][k] = cumsum[k]
print(dp[N][K])
```

# 思考順序
## 愚直な実装

素直に実装すると

```python
dp = [[0] * (K + 1) for _ in range(N + 1)]
dp[0][0] = 1
for i in range(1, N + 1):
    for k in range(K + 1):
        capacity = Capacities[i - 1]
        for n in range(capacity + 1):
            if k - n >= 0:
                dp[i][k] += dp[i - 1][k - n]
                dp[i][k] %= MOD
print(dp[N][K])
```

これだと計算量が$O(NK^2)$

## ループを減らす

例で考えてみましょう

ex) N = 3, K = 4, a = (1,2,3)
最終的なDPテーブルは以下の通り

```python
[1, 0, 0, 0, 0]
[1, 1, 0, 0, 0]
[1, 2, 2, 1, 0]
[1, 3, 5, 6, 5]
```

例えばdp[2][2]を求めるとき、考える遷移は

$$
dp[2][2] = dp[1][0] + dp[1][1] + dp[1][2]
$$

つまり、1つ前の行の累積和$cumsum$が計算できていれば、$cumsum[a_i]$で求められます

## 区間の和は累積和の差
また、別の例を考えてみます

ex) N=3, K=4, a = (2, 1, 1)

dp[2][2]を求めるとき、考える遷移は

$$
dp[2][2] = dp[1][1] + dp[1][2]
$$

です。

これもdp1行目の累積和$cumsum$が計算できていれば

$cumsum[2]-cumsum[2-a_2 - 1] = cumsum[2] - cumsum[0]$ 

で求めることができます。

- 1列目から2列目までの和 = 2列目までの累積和 - 0列目までの累積和

## 実装

1. 1行前の累積和を計算する
2. 累積和を使って、dpテーブルを更新する

こうすると、ループを1つ減らせて計算量は$O(NK)$

```python
for i in range(1, N + 1):
    cumsum = [0] * (K + 1)
    cumsum[0] = dp[i - 1][0]
    for k in range(1, K + 1):
        cumsum[k] = cumsum[k - 1] + dp[i - 1][k]
        cumsum[k] %= MOD
    for k in range(K + 1):
        capacity = Capacities[i - 1]
        min_limit = k - capacity - 1
        if min_limit >= 0:
            dp[i][k] = (cumsum[k] - cumsum[min_limit]) % MOD
        else:
            dp[i][k] = cumsum[k]
```

MODで割るのを忘れずに(1敗)
assertThatとは

## assertThat

:::note
**JUnitやHamcrestを使用して、テストコード内で条件を検証するためのメソッド**
:::



テスト対象の実行結果やオブジェクトの状態を、期待する値や条件と比較する
比較結果が一致しない場合は、テストがFailする

## assertThatの例

### このメソッドをテストする

```java
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}
```
### assertThatを使ってテストする

```java
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class CalculatorTest {

    @Test
    public void testAdd() {
        Calculator calculator = new Calculator();

        // メソッドの実行結果をテスト
        int result = calculator.add(3, 5);

        // assertThatとHamcrestのマッチャーを使って結果をテスト
        assertThat(result, is(equalTo(8))); // 3 + 5 = 8

        // 他のマッチャーを使ったテストの例
        assertThat(result, is(not(equalTo(10)))); // 結果は10と等しくない
        assertThat(result, is(greaterThan(5))); // 結果は5より大きい
    }
}
```
【ChatGPT無】コードブロックいらないよぉ（妥協編）

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::

　どうも、カーブミラーです。

　今回は、
[【ChatGPT無】コードブロックいらないよぉ](https://qiita.com/kabumira/items/8d70bc9aa02c6ba7a907)
　　の第二段です。

　と言いますか、
　　解決編かも。

　さんざん、繰り返した結果、
　　最終的に諦めました（泣）

　いや、
　　コードブロックを
　　　なくして、
　　　　マークダウン記法を
　　　　　出力する気は
　　　　　　諦めていません。
　　　　　　　（しつこいw）
***
　とにかく、
　　どうやっても
　　　コードブロックされるので、
　　　　「もう仕方ない」
　　　　　と諦めました。

　その代わり、
　　まずは、コードブロックでの
　　　出力をさせます。

　次に、その出力に対して、
　　コードブロックの
　　　開始と終了のマーク
　　　　である「```」を
　　　　　削除させることに
　　　　　　しました。

　わかります？

　まぁ、
　　実際に見た方がいいですかね。
　　　どうぞ。

　ChatGPTさんが出力した
　　コードブロック排除？
　　　の結果です。
***
もちろんです。以下はマークダウン記法のサンプルテーブルです：

```
| 列1 | 列2 | 列3 |
|-----|-----|-----|
|  1  |  2  |  3  |
|  4  |  5  |  6  |
|  7  |  8  |  9  |
```

「```」を外した出力は以下の通りです：

列1 | 列2 | 列3 
-----|-----|-----
  1  |  2  |  3  
  4  |  5  |  6  
  7  |  8  |  9  

お好みでご利用ください！
***
　ということです。

　では、Promptをどうぞ。

```Text:コードブロック排除？Prompt
サンプルデータで構いませんので、マークダウン記法のテーブルを出力してください。
その出力から、「```」をすべて外して、出力しなおしてください。
```
　上の行が、
　　目的物ね。

　下の行が、
　　コードブロックの削除指示です。

　出来たぁ（嬉）
RustでCargo.tomlが正しいのにno targets specified in the manifestエラーが出る

# はじめに

Rustで新たなモジュールを作成したときに`rust-analyzer`が動かなくなり解決に時間がかかってしまったので、こういう問題もあったよというのを共有しておきます

# 問題

`rust-analyzer`が以下のようなエラーを出してビルドができなくなりました

```
failed to load manifest for workspace member `/home/watanabejin/workspace/music-api-proxy/music-bff/.`

Caused by:
  failed to load manifest for dependency `gateway`

Caused by:
  failed to parse manifest at `/home/watanabejin/workspace/music-api-proxy/music-bff/gateway/Cargo.toml`

Caused by:
  no targets specified in the manifest
  either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present
```

`gateway`配下の構成になっており、`Cargo.toml`も問題なさそうでした

```
┣ gateway
  ┣ Cargo.toml
  ┣ src
    ┣ gateway.rs
    ┣ libs.rs
```

# 解決方法

問題は`ファイル名`でした

`libs.rs`でなく`lib.rs`でないとうまく`mod`が読み込めていませんでした

# おわりに

ファイル名のミスで30分時間を取られました
久しぶりにこれ系統のミスをしたなと思いましたので、同じ問題を抱えている初心者が幸せになれば嬉しいです
WSL2 Docker Desktop 環境でDockerデーモンが存在しないエラー Cannot connect to the Docker daemon at unix:///var/run/docker.sock

## 概要

WSL2 Docker Desktop の環境でDockerデーモンが起動せず、困っていたので解決方法を残します。

## エラー

```
$ docker run hello-world

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

## 確認

```
$ sudo cat /var/log/docker.log
```

ログファイルがない

Docker Desktopのログを探すもエラーが見つからない。
`C:/Users/<User Name>/AppData/Local/Docker/log.txt`

## ダメだった方法

Dockerデーモンを起動する

```
$ sudo service docker start

or

$ systemctl start docker
```

↑大体の記事はこのコマンドを実行すると解決するとあるが、解決しなかった。

WindowsのプロンプトでWSL2自体を再起動

```
wsl.exe --shutdown
```

特に効果なし。

パソコン自体を再起動するも、効果なし(絶望

## 解決方法

うまくいかないので普通にうまく行ってる人の記事をみて設定が同じか確認していく。

Docker for Windows > Settings > Resources > WSL Integration

`Ubuntu` の設定がなぜかオフになっていたので、有効にすると解決した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/ed97a9e2-51e1-c570-3688-7a4a3834a5b0.png)

## さいごに

なぜオフになっていたのかは謎のままです。
あとオフになってても動く人は動くらしいです。

詳しい人いたら教えてください。
ライブラリとフレームワークの違いについて

# 概要
ライブラリとフレームワークの違いは、大まかに、部品をまとめた”ファイル”がライブラリで、全体の枠組みを用意した”テンプレート”が、フレームワークである。
ただ、境界はやや曖昧。特にVue.jsやReactは、どちらとも言える。
必要なものだけ一部を使うライブラリに対して、フレームワークは全体をベースとしてほぼそのまま使うというイメージ。

# ライブラリ
さまざまな機能を、単に「必要に応じて使ってください」と用意したもの。

利用する側が、「ここでこういうことをしたいから、その機能を呼び出そう」といった使い方をする。

### ライブラリの例
jQuery, Node.js

# フレームワーク
ライブラリを強化したようなもの。

時や場合によって特定の機能を呼び出すのではなく、フレームワークは、プログラム全体の構成を決める。
プログラマは、フレームワークで決められた仕様にしただって、プログラムを用意していく。

「こういう場合は、ここにこういう形でプログラムを用意してください」というように、フレームワーク側からプログラムに指示を出す。

### フレームワークの例
Laravel, Vue.js, Bootstrap, Tailwind CSS
GoogleColaboratoryはjavascript・htmlも使用できる

# 結論
セルマジックを使うことでjavascript・htmlが使用できます

# セルマジックとは
下記の記事が参考になります。

https://qiita.com/mgsk_2/items/437656b8ce42c03e41a6

https://qiita.com/kazoo04/items/a0bd374199a7783ca0e

# サンプルコード
### javascript

```.js
%%javascript
const div = document.createElement('div');
div.textContent ='Hello world!';
document.body.appendChild(div);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/caa6d317-569b-7467-0c7c-c62ee5495e45.png)

-----

### html
```.html
%%html
<div>hello world</div>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/62201864-6c0d-2320-eb96-4962aa4f85b8.png)

-----

実はmarkdown・latexも使用できるようです。

### markdown
```.md
%%markdown
# HelloWorld!
- hello
  - world
1. hello
1. world

|a|b|
|-|-|
|c|d|
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/672d2f5f-3cd5-0074-476b-b0caf389884e.png)

-----

### latex
```
%%latex
A_1 = 1\\A_{i + 2} = A_{i + 1} + A_i
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/de5c5725-2597-2fc1-17a0-1a7264b40402.png)

以上です。

# 参考

https://qiita.com/kazoo04/items/a0bd374199a7783ca0ee

https://qiita.com/mgsk_2/items/437656b8ce42c03e41a6

https://ipython.readthedocs.io/en/stable/interactive/magics.html#cell-magics
SAP on Azure デプロイ自動化フレームワークをいろいろ触ってみた

# はじめに
SAPシステムを構築する際、前提条件としてやらなきゃいけないことや意識しないといけないことが多いです。手動で作成していく際はかなりの時間が必要になります。

今回、私の方で構築の自動化を検証する機会があったため、気になっていた「SAP on Azure デプロイ自動化フレームワーク」を触ってみました！
大変だったことやどのようなことをしたのかをブログで共有していけたらなと思います。

# SAP on Azure デプロイ自動化フレームワークとは？
詳しくはMicrosoftさんのブログを熟読する必要がありますが、このフレームワークを利用することでSAP推奨構成でシステムを構築できるようになります。

https://learn.microsoft.com/ja-jp/azure/sap/automation/deployment-framework

インフラ領域（Azure側のインフラ）の構築作業は、「Terrafome」
仮想マシン内の設定作業は、「Ansible」で実施します

# 今回の構成
今回は、**Greenfield**シナリオ（新規構築）でいきます。
Greenfieldについての詳細説明は弊社ブログをご確認ください。

https://www.beex-inc.com/blog/s4hana-brownfield-greenfield

システムを新規構築すると以下のようなリソースが作成/配置されていきます。
構築はほぼデフォルト設定ですが、今回費用的なところ含めて不要なリソース作成しないような形で構築しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3521211/931da552-aab8-66e5-b7d4-52b1bab782e3.png)

# では、実際の構築に進みます・・・
ごめんなさい(笑)
記載することがかなり多いと思うのでいったん区切ります。
ブログ投稿（Markdown記法）に慣れず、時間かかってしまいますが頑張っていきます。

# 次回予告
SAPシステムを構築するにあたり、まずはコントロールプレーンを用意しなければいけませんので、次回「コントロールプレーン」の作成の記事を投稿します！
[AWS] SCPでできること

AWSアカウント全体でやっていいこと、やっちゃいけないことをAWS OrganizationsのSCPで制限したいケースがあると思うのですが、ご作法が色々あるので、備忘録的にメモする。


## Principal/NotPrincipal句をかけない。
* 代わりにConditionでがんばる

```{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyAssumeRoleToKeyMGRfromSSOuser",
      "Effect": "Deny",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::*:role/testRole0*",
      "Condition": {
        "ArnLike": {
          "aws:PrincipalArn": "arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/ap-northeast-1/AWSReservedSSO_myTestAccessPermissions_*"
        }
      }
    }
  ]
}
```
* Condition句でPrincipalを指定する場合は、PrincipalArnで指定するのがわかりやすいPrincipalArnで指定できるパターンは以下の4つ（[ユーザガイド](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-principalarn)）
    * IAM ロール(arn:aws:iam::123456789012:role/role-name)
    * IAM ユーザー(arn:aws:iam::123456789012:user/user-name）
    * AWS STS フェデレーションユーザーセッション(arn:aws:sts::123456789012:federated-user/user-name)
    * AWS アカウント ルートユーザー(arn:aws:iam::123456789012:root）

```
⭕️ "aws:PrincipalArn": "arn:aws:iam::*:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_*" iamはユーザでもOK
⭕️ "aws:PrincipalArn": "arn:aws:sts::123456789012:federated-user/user-*" # sts/federated-userはOK
❌ "aws:PrincipalArn": "arn:aws:sts::*:assumed-role/AWSReservedSSO_*"    # sts/assumed-roleはかけない
```

   * IAM Identity CenterとかでSSOしてたり、踏み台AWSアカウントとかを使っているとassumed-roleのArnを使いたくなるが、aws:PrincipalArnではassumed-roleは指定できないので要注意。

## Resource句はDenyでしか使えない。（Allowでは*としか書けない）
そして、NotResourceはAllowでもDenyでも使えない。

⭕️　できること
* このリソースはこの人しか使っちゃダメ（PrinsipalArnのStringNotEquals条件を使ったResouce指定Deny）
* このリソースタイプは使っちゃダメ（ワイルドカードResouce指定Deny）

❌　できないこと
* このリソースタイプだけなら使ってOK（Allow）
* この人はこのリソースのみ使ってOK（Allow)
* このリソース以外は使ってOK（Allow）
* このリソース以外は使っちゃダメ（NotResourceを使用したDeny）

以下はユーザガイドより
> Effect 要素に Allow の値があるステートメントでは、SCP の Resource 要素の「*」のみを指定することができます。個々のリソースの Amazon リソースネーム (ARN) を指定することはできません。
https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps_syntax.html#scp-syntax-resource

> リソース要素でアスタリスク (*) や疑問符 (?) などのワイルドカード文字を使用することもできます。
https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps_syntax.html#scp-syntax-resource

## NotAction句はDenyでしか使えない。
普通にNotActionはDenyで使うことが多いと思うので、これはあまり気にならないはず。IAMポリシーとかだとNotActionを使ったAllow（このAction以外は使ってOK）という書き方はできるけど、無秩序な許可に繋がりやすいのでできるだけ使わない方が良い。



## おすすめの使い方

おすすめの使い方がユーザガイドで公開されている。まずはそこから入るとよい。
https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps_examples_general.html

* _リージョン制限_
特定リージョン以外でのAPI実行は禁止する

* _特権管理者以外による重要リソースの変更禁止_
特定のIAMロールやSSOユーザ以外は、全体統制に関わる重要リソースの操作ができないように制限する。たとえばアラート通知用SNS Topicの削除を禁止する。

* _ルートユーザの使用禁止_
Control Towerで払い出したAWSアカウントとかではrootユーザを使うシーンはほとんどないので、rootユーザはSCPで何にもできないようにしておくのがおすすめ。ちなみに、rootユーザでないとできないオペレーションは[ユーザガイド](https://docs.aws.amazon.com/ja_jp/accounts/latest/reference/root-user-tasks.html)にリストされている。
Spring boot3  Security(JWT)にハマったところ

■認証アルゴリズムが変わった

今までは「SignatureAlgorithm.HS512」を使っていたのですが、
Spring boot3 Spring Security6だと動かないので「SignatureAlgorithm.HS256」に変更しました。
デフォルトのアルゴリズムもHS256のようで、切り替えは早めにやったほうがいいですね。

``` java
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.io.Decoders;

  private Key getSignInKey() {
    byte[] keyBytes = Decoders.BASE64.decode(secretKey);
    return Keys.hmacShaKeyFor(keyBytes);
  }
```

signWithは以下のように書きます。
Jwts.builder().signWith(getSignInKey(), SignatureAlgorithm.HS256)


■WebSecurityConfigurerAdapterは非推奨で継承してはいけない
→変わりにfilterChainを使用してください。

・変更前

```java
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
    }

}
```


・変更後
```java
@Configuration
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
        return http.build();
    }

}
```

引用サイト：
https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter
vue3でsvgやmdなどフォルダ内にあるファイルを変数でDynamic import(required)でComponentする

iconComponentやpostComponentなど、静的ファイルmoduleを動的に読み込みたい場合のSolution。

ES5では、requiredで変数を使った動的読み込みが可能で、ES6ではどうする？

```
required(`./${file}.svg`)
```
→ TSだとlintが反応するので`required`使えないので`import`を利用する

## defineAsyncComponentを利用する
https://ja.vuejs.org/guide/components/async.html

> ES モジュールの動的インポートも Promise を返すため

ここがポイントですね。

以下はiconComponentの利用例ですが、vue3(vite)の場合、`vite-svg-loader`を利用すればsvgをComponentととして取り扱えるので、以下のようなComponentが作成できます。

```vite.config.js
import svgLoader from 'vite-svg-loader'

export default defineConfig({
  plugins: [
    vue(),
    svgLoader()
  ]
})
```


```IconBase.vue
<script setup>
import { defineAsyncComponent } from 'vue';

const props = defineProps({
  name: string
});

// svgファイルを非同期読み込み
const iconFile = defineAsyncComponent(() =>
  import(`./icons/${props.name}.svg`)
);
</script>

<template>
  <component :is="icon" />
</template>
```
`<component>`が`<svg ... />`に展開される。
同じようにmd-loaderをつかえば、mdを展開できる。
【Azure Cognitive Search】スキルセットの設定にめちゃくちゃハマったのでメモ

# やりたいこと
Cognitive Searchで検索した結果をテキストを分割してその結果を取得したい。
調べてたところ、標準スキルセットに**テキスト分割コグニティブ スキル**なるものがあったので、それを使ってみようとした備忘録

https://learn.microsoft.com/ja-jp/azure/search/cognitive-search-skill-textsplit

# 概念
ざっくり描くと以下の図のような感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420694/b544bac5-4f47-1f0b-d9ca-0d9e2efb38b1.png)

:::note warn
細かいことを指摘すると全然違いますがひとまず気にせず･･･
:::

## テキスト分割スキルの設定

設定には3つの準備が必要です。
- スキルセットのJSONへテキスト分割スキルに関する定義を追加
- インデクサーのJSONにスキルセットで処理した出力をインデックスにマッピングするための設定
- スキルセットで処理した出力を格納する任意のインデックス

**<font color="red">ここでややこしいのが、
スキルセットやインデクサーの設定がすべてJSONのテキストベースで行われることと、Cognitive Searchでの内部的なデータの構造がパッと見ではわかりにくいことがあります。</font>**
正直JSONでガリガリ設定することに耐性がないとこの時点で結構やる気をそがれそう・・・

一応公式のドキュメントをちゃんと読めば分からなくはないですがハードルが高いんですよね。

https://learn.microsoft.com/ja-jp/azure/search/cognitive-search-working-with-skillsets


今回は以下のような内容で作成します。
- データ本文 **/document/content** をテキスト分割処理にかけて
- テキスト分割後のデータを **/document/content/splitData** に格納し
- インデクサー側で **/document/content/splitData** を **/document/pages** にマッピングする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420694/fa248d6e-b296-7c4b-6f70-116e5731922f.png)

### スキルセットに設定する定義
スキルセットのJSONに下記を追加します。
```json
    {
      "@odata.type": "#Microsoft.Skills.Text.SplitSkill",
      "name": "#2",
      "description": "",
      "context": "/document/content",
      "defaultLanguageCode": "ja",
      "textSplitMode": "pages",
      "maximumPageLength": 300,
      "inputs": [
        {
          "name": "text",
          "source": "/document/content"
        }
      ],
      "outputs": [
        {
          "name": "textItems",
          "targetName": "splitData"
        }
      ]
    }
```
inputsのsourceにテキスト分割元になるデータを指定します。
outputs側のtargetNameにテキスト分割後にデータが格納されるカラムを記載します。

:::note
このとき、targetNameはパスでは記載しません。記載したカラム名がinputsのsourceに指定したパスの階層として作成されます。（今回で言うと、 **/document/content/splitData** に格納される）
:::

### インデクサーに追加する定義
このままではインデックスに配置できないので、
インデクサー側のJSONにフィールドのマッピングを設定する。
```json
  "outputFieldMappings": [
    {
      "sourceFieldName": "/document/content/splitData",
      "targetFieldName": "pages"
    }
  ]
```
今回の場合、
テキスト分割で生成された **/document/content/splitData** の内容を、**pages** フィールドにマッピングさせる。targetFieldNameはパスで記載する必要はありません。

### 参考：全体の繋がり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420694/a604c64f-788a-8303-debf-5437f5f6c574.png)

## 試す
まずインデクサーを実行する必要があります。
既にインデックスを作成している場合は一度リセットをしてから、再度インデクサーを実行してください。

インデクサーの実行が完了したら、エラーが無いかを確認します。
インデクサーの実行画面からエラーや警告を確認することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420694/75e90cb7-a433-03d6-52a2-2501b267d895.png)

その後、インデックスの画面で検索を行い、テキスト分割が行われていることを確認してください。
出力のマスキングがめんどくさいので、ここのキャプチャは省きますが、上記設定であればpagesフィールドにテキスト分割結果が入ってきます。

# おわり
JSONで設定をやるのはちょっと大変ですね･･･
今後、Azure OpenAI ServiceのGPTモデルへのAdd User Dataがリリースされて、
あまり深いことを考えずにCognitive Searchを使えるようになりましたが、
最適なものを作成するためには、Cognitive Search本体の仕組みをしっかり理解しておくことが重要かもしれませんね。
Extend NPSP Data Importer with Advanced Mapping


+ [Extend NPSP Data Importer with Advanced Mapping](https://trailhead.salesforce.com/content/learn/projects/extend-npsp-data-importer-with-advanced-mapping)

# Map Standard and Custom Fields on a Standard Object

+ [Map Standard and Custom Fields on a Standard Object module unable to verify](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000078SJbh)

:::note alert
We couldn’t find both the preferred language and email opt-out fields for Contact2 on your NPSP Data Import object. Make sure you followed the instructions above to set it up.
:::

:::note
the type of Email Opt Out is not picklist but checkbox. we can not change it.
:::


何もしないで検証ボタンを押してみる

:::note alert
We couldn’t find both the preferred language and email opt-out fields for Contact1 on your NPSP Data Import object. Make sure you followed the instructions above to set it up.
:::

もしかしたら、Preferred Languageという選択肢セットは既に作っていた（記憶がないけど）ので、違うエラーになったかもしれません。

あれ、Preferred Languageというフィールドも作っててなぁ。

Contact1 Preferred Languageを作ってみた

:::note alert
We couldn’t find both the preferred language and email opt-out fields for Contact1 on your NPSP Data Import object. Make sure you followed the instructions above to set it up.
:::

Contact1 Email Opt Outを作ってみた

:::note alert
We couldn’t find both the preferred language and email opt-out fields for Contact2 on your NPSP Data Import object. Make sure you followed the instructions above to set it up.
:::

Contact2 Preferred Languageを作ってみた

:::note alert
We couldn’t find both the preferred language and email opt-out fields for Contact2 on your NPSP Data Import object. Make sure you followed the instructions above to set it up.
:::

Contact2 Email Opt Outを作ってみた

:::note alert
We couldn’t find the Contact1 Preferred Language field mappings we were looking for. Make sure you followed the instructions above to set them up correctly.
:::


# トレイルヘッドの質問

+ [We couldn’t find both the preferred language and email opt-out fields for Contact2 on your NPSP Data Import object. ](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000078SJbh)

:::note
Are you setting the page layout for On the NPSP Data Import record as follows?

Move the Contact2 Preferred Language and the Contact2 Email Opt Out fields to the corresponding locations in the Contact2 Information area.

https://trailhead.salesforce.com/content/learn/projects/extend-npsp-data-importer-with-advanced-mapping/map-standard-and-custom-fields-on-a-standard-object
:::


+ [Whoops, looks like there was a problem. Please try again.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000078SJbh)
AmazonLinux2023にAWS CDK開発環境構築

# 環境情報

```shell-session
$ ec2-metadata --ami-id
ami-id: ami-08c84d37db8aafe00

$ cat /etc/system-release
Amazon Linux release 2023 (Amazon Linux)

$ uname -a
Linux example.ap-northeast-1.compute.internal 6.1.38-59.109.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Jul 11 23:51:29 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

$ aws --v
aws-cli/2.9.19 Python/3.9.16 Linux/6.1.38-59.109.amzn2023.x86_64 source/x86_64.amzn.2023 prompt/off
```

# node.jsのインストール

```shell-session
# ノードバージョンマネージャー (nvm) をインストール
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash

# コマンドラインで次のように入力して、nvm を有効化
. ~/.nvm/nvm.sh

# nvm を使用して Node.js の最新バージョンをインストール
nvm install --lts
```

```shell-session
# バージョン指定したい時
nvm install v16.20.1
# 使用するバージョンを変えたい時
nvm use v16.20.1
# デフォルトバージョン変えたい時
nvm alias default v16.20.1

# バージョン確認
node -v
v18.17.0
```

# AWS CDK Toolkit をインストール

```shell-session
$ npm install -g aws-cdk

$ cdk --version
2.89.0 (build 2ad6683)
```

# 開発を始めましょう！

CDKアプリの作成
```shell-session
$ mkdir cdk-app
$ cd cdk-app
$ cdk init app --language typescript
```

ブートストラップ（CDKリソースのプロビジョニング）
```shell-session
$ cdk bootstrap
 ?  Bootstrapping environment aws://123456789012/ap-northeast-1...
```

※（cdk initする前など）CDKアプリ（cdk.json）の無いディレクトリでbootstrapするとデプロイ先を指定してくれとエラーが出るので、先にcdk initするか、デプロイ先を指定します。（他者が作成したCDKアプリをcloneする等して、そのディレクトリ内で実行しても良い）
```shell-session
$ cdk bootstrap
Specify an environment name like 'aws://123456789012/us-east-1', or run in a directory with 'cdk.json'.

$ cdk bootstrap aws://[ACCOUNT-NUMBER]/[REGION]
```


# 参考
https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html

https://github.com/nvm-sh/nvm#installing-and-updating

https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_install

https://cdkworkshop.com/15-prerequisites.html

https://docs.aws.amazon.com/cdk/v2/guide/hello_world.html

https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html
いいね！機能の実装方法

## いいね機能の実装方法をこちらに記載致します。

まず最初にmoelのlike.rbを作成し、その後、ユーザーモデルと投稿にあたるモデルにhas_manyを使って関連づけます。

```
class Like < ApplicationRecord
  belongs_to :user
  belongs_to :shop
end
```

```
class User < ApplicationRecord
  has_many :likes
end
```
```
class Shop < ApplicationRecord
  has_many :likes
end
```
続いていいね！ボタンを表示したいファイルでの書き方を説明します。
ボタンを押すことにより、見た目が変化するため、if文を設置する必要があります。

```
<% if current_user.likes.exists?(shop_id: shop.id) %>
  <%= link_to delete_like_path(shop), method: :delete, class: "like-btn" do %>
    <i class="fas fa-heart liked"></i>
  <% end %>
<% else %>
  <%= link_to like_path(shop), method: :post, class: "like-btn" do %>
    <i class="far fa-heart"></i>
  <% end %>
<% end %>
```


以下のコードをroutes.rb内に記載します。

```
resources :likes, only: [:create, :destroy]
```

そして、次にcontrollerファイルを作成し、いいね！をした時としてない時のアクションを作成します。

```

class LikesController < ApplicationController
  before_action :authenticate_user! # ユーザーがログインしていることを確認するフィルター

  def create
    @shop = Shop.find(params[:id])
    current_user.likes.create(shop: @shop)
    redirect_to shop_path(@shop), notice: 'いいね！しました。'
  end

  def destroy
    @shop = Shop.find(params[:id])
    current_user.likes.find_by(shop: @shop).destroy
    redirect_to shop_path(@shop), notice: 'いいね！を解除しました。'
  end
end
```

また、ボタンに動きを付けるためにapp/assets/javascriptsにshop.jsを追加する必要があります。
コード内容は以下のようになっています。
```
<% @shops.each do |shop| %>
  <div class="shop-tile">
    <!-- Shopの情報表示部分 -->

    <!-- いいねボタン -->
    <div class="like-btn">
      <% if current_user.likes.exists?(shop_id: shop.id) %>
        <%= link_to delete_like_path(shop), method: :delete, class: "unlike-link" do %>
          <i class="fas fa-heart liked"></i> いいね解除
        <% end %>
      <% else %>
        <%= link_to create_like_path(shop), method: :post, class: "like-link" do %>
          <i class="far fa-heart"></i> いいね
        <% end %>
      <% end %>
    </div>
  </div>
<% end %>
```

これらのコードを書くことにより、いいね！ボタンの機能を実装することが出来ます。
【AWS】Lambdaのyamlによる移管方法


## 1. Lambdaソースのダウンロード
まずは、移管対象のLambdaのSAM(yaml)とデプロイパッケージ(zip)をダウンロードする。
1. 移行する Lambda 関数のコンソール画面へ移動
2. Lambda 関数ウィンドウで [アクション] を選択し、[関数のエクスポート] を選択
    ![Lambda_SAM1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/30b9c14b-13e7-1190-8502-4b28914b3d6c.png)
4. [ AWS SAM ファイルのダウンロード ] を選択してダウンロード
5. [デプロイパッケージのダウンロード] を選択してダウンロード
    ![Lambda_SAM2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/aee40a52-dd28-c5ee-cb11-5aa2b93a63b1.png)

## 2. 移行先のAWSのS3にデプロイパッケージをアップロード
1. 適当なバケットに先ほどダウンロードしたデプロイパッケージ(zip)をアップロードする
1. ファイルのS3 URIをコピーしておく
![Lambda_SAM3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/819e64c6-1693-5f8d-9c3c-d15738ace904.png)

## 3. CloudFormationでLambda 関数をデプロイする
AWsサービス構成ファイルであるSAM(yaml)を移管先へ修正して、CloudFormationで構築する。

1. ダウンロードしたSAM ファイルを開く
    ```
    AWSTemplateFormatVersion: '2010-09-09'
    Transform: 'AWS::Serverless-2016-10-31'
    Description: An AWS Serverless Specification template describing your function.
    Resources:
      *******:
        Type: 'AWS::Serverless::Function'
        Properties:
          Handler: lambda_function.lambda_handler
          Runtime: python3.11
          CodeUri: s3://*********/*******************.zip
          Description: ''
          MemorySize: 128
          Timeout: 3
          Role: 'arn:aws:iam::**********:role/AWSLambda-ExecutionRole'
          RuntimeManagementConfig:
            UpdateRuntimeOn: Auto

    ```
1. SAM ファイルを編集する
     - CodeUri: の後に、S3 URIを記載する
     - Lambda用にIAM Roleを作成する ```AWSLambda-ExecutionRole```
     - Role:の後に、Lmabdaに付与したいRoleのarnに置き換える
     - その他、Runtime:やLayer:を適宜書き換える
1. CloudFormationのコンソール画面で、スタックの作成を押す
    ![Lambda_SAM4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/774329e8-eb26-e83a-29b8-5a501817dbfe.png)
1. テンプレートの指定からテンプレートファイルのアップロードを押し、SAMをアップロードする
1. 次へを押す
1. スタック名を決める。このスタック名はLambda関数名の先頭文字 ******-元の名前-ランダムな文字列になる
1. 次へを押す
1. 次へを押す
1. 3か所チェックを入れて、送信を押す

## 参考文献

https://repost.aws/ja/knowledge-center/lambda-function-migration-aws-sam

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-add-tags.html
macOSでマウスポインタ(カーソル)の見た目を変える方法

# 設定で変える
### ポインタのサイズを変更する
`設定>アクセシビリティ>ディスプレイ>ポインタ`の`カーソルのサイズ`からお好みのサイズへ。
### ポインタの色を変更する
`設定>アクセシビリティ>ディスプレイ>ポインタ`の`ポインタの枠線のカラー`や`ポインタの塗りつぶしのカラー`をお好みの色にする。
# ソフトを入れて変える
### MouseCapeの導入
macOSには、マウスポインタの色を変える機能しかついていないが、MouseCapeを使用することで画像をポインタにできる。また、アニメーションも可能。
[ここ](https://github.com/alexzielenski/Mousecape/releases)からダウンロードして開く。権限とか求められたら許可しておくこと。

ポインタを作るソフトをこれから2つ紹介するが、CursorCreateは不具合が多い気がするので個人的にはMouseCapeだけで済ませるのをお勧めする。一応、CursorCreateについても軽く紹介する。

### CursorCreateでポインタのファイルを生成
CursorCreatorでマウスポインタに使いたい画像を読み込む。Gifも対応。
CursorCreatorは[ここ](https://github.com/isaacrobinson2000/CursorCreate/releases)からダウンロード。
CursorCreatorの使い方がわからなかったらコメントして。
CursorCreatorではwindows、macOS(MouseCape)、Linuxなどのポインタを生成してくれる。なので、複数のOSで同じマウスポインタを使いたい人にお勧め。
完成したら、Build Projectを押して名前と生成先を選んでokを押す。
生成されたフォルダを開くとフォルダが4つあると思うのでその中のmousecape_macosに<自分でつけた名前>.capeというファイルがあれば生成成功。MouseCapeでの読み込み方は後で解説。

### MouseCapeでポインタファイルを作成する
MouseCapeを開き、上のメニューバーのFileの中にある、New Capeを押す。そしたら、Unnamedというのが追加されるので、そこを右クリックしてEditを押す。そしたら、編集画面が出てくる。
わかりやすく画像で説明するとこんな感じ![スクリーンショット 2023-08-04 10.04.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474952/89f7f820-7967-137a-ed41-7edb243944e0.png)

ポインタを追加したい場合は左下の+ボタンを押す。そしたら、unknownっていうのができるのでそこを押して、ポインタに使いたい画像を下にある1x、2x、5x、10xのどれかにドラッグすると画像が読み込まれる。1x、2x、5x、10xのどこにドラッグするかで、ポインタのサイズが変わる。ただ、後からSizeで変えられる。
次に、編集画面にある項目の説明をする。
Typeはマウスポインタの種類。通常時のポインタはArrow。(他の種類も知りたかったらコメントすれば、多分返事する。)
FramesとFrame Duarationはポインタにアニメーションをつけたい時に使う。アニメーションの付け方は、[この](https://youtu.be/fUPOL8gwTk8)動画が参考になる。自分は、PhotoShopを持っていないので[PhotoPea](https://www.photopea.com/)で代用した。
Hot Spotはクリックされる位置(赤い点で表示される)
Sizeはポインタのサイズ

編集が完了したら、メニューバーのFileからSaveを押して(⌘S)から、編集画面を閉じる。
そしたら、編集したポインタを右クリックしてApplyを押せば適用される。もし、これで反映されなかったらコメントしてくれれば多分対応する。

### 自分で作ったポインタを誰かに共有したい場合
共有したいポインタを右クリックしてShow in Finderをクリック。その中に<ファイル名>.capeというファイルがあるのでそのファイルをGitHubで公開したり、Google Driveで共有したり、AirDropするなどして相手にダウンロードしてもらえばok。

### .capeファイルの読み込み方
CursorCreateでポインタを作った場合や、共有されてるものをダウンロードした場合は、capeファイルとなっているのでその読み込み方を説明します。
MouseCapeを開き、メニューバーのFileのImport Capeを押して(⌘Oで代用)、読み込みたいcapeファイルを選択してImportを押せば読み込まれます。
読み込んだら、右クリックしてApplyを押せば適用されます。

## 最後に
ポインタを作ってでGitHubで公開しました。[リリースページ](https://github.com/U5KUN/My-MouseCapes/releases)
書き終わって思ったが、「そしたら」が2連続でくるのどうにかしてほしい。
あと、多分返事するっていうのは、75%くらいです。
UbuntuにAnsibleをインストール

## 目的
Ansibleを使ってterraformでプロヴィジョニングをしたVMに、k8sを導入する必要が出てきた。今回は、ansibleを導入する。

## インストール
```shell
sudo apt update
sudo apt -y install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt -y install ansible
```

## 確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/23bff5fa-561c-7839-1815-0f56d7fa8ec7.png)
RealTimeDataBaseを使っていると突然"401 Unauthorized"が出るようになる

# 原因
GCP or FirebaseのRealtimeDataBaseをDefault状態で利用しているとアクセス可能な期限が作成日から20日間に設定されるようです。

# 対策
特に期限の設定が必要ないのであれば、 `ルール`タブからルールを延長または無期限に設定することで再度アクセスできるようになります。

### 設定変更前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/aadf7069-a231-6112-1f36-ca48d8198fbd.png)

### 設定変更後（無期限にする場合）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/7581f5f1-a987-5bfa-532d-2d5a248fe141.png)

以上
This version of PlantUML is xxx days old

Visual Studio Codeで `This version of PlantUML is xxx days old` と言われてプレビューが表示できない場合の対応。

1. [こちら](https://plantuml.com/ja/download)から最新のplantuml.jarを入手する
1. `~/.vscode/extensions/jebbs.plantuml-x.x.x`のplantml.jarを↑で入手した最新版に変更する
1. VSCodeを再起動する

サーバーレンダラーを使ったほうがいいとREADMEに書いてあるけど、とりあえずこれで回避した。
mocker.spyの使い方、使い所


## mockとは
- mockとは依存する関数やクラスが正しく使われているかどうかをテストする時に使われるオブジェクト
- mockerを用いると指定した対象を偽の実装にすり替えて、引数や呼び出し回数を保存できるオブジェクト（すなわちモック）にすることができる。

## moker.spyとは
- 指定した対象の本物のメソッドを呼びつつ呼び出し回数を確認や引数、返り値を確認できる。

## 使い所
テスト実行時に
- コントローラからjobのテストをしたい時
- 外部システムへアクセスする際




## 使い方
指定した対象をmock化し後続でtestしたいものをcallする
[Spyより](https://pytest-mock.readthedocs.io/en/latest/usage.html#spy)

methodをテストする場合
```
def test_spy_method(mocker):
    class Foo(object):
        def bar(self, v):
            return v * 2

    foo = Foo()
    spy = mocker.spy(foo, 'bar')
    assert foo.bar(21) == 42

    spy.assert_called_once_with(21)
    assert spy.spy_return == 42
```
funcitonをテストする場合
```
def test_spy_function(mocker):
    # mymodule declares `myfunction` which just returns 42
    import mymodule

    spy = mocker.spy(mymodule, "myfunction")
    assert mymodule.myfunction() == 42
    assert spy.call_count == 1
    assert spy.spy_return == 42
```
- spyの返すオブジェクト
    - 基本的にはmockと同じものが使えるが加えて２つ追加されている。
    - spy_return: spyされた戻り値
    - spy_exception: spyされた関数/メソッドが最後に呼び出されたときに発生した例外の値。
Flutterで文字コードを変換する　charset_converterの使い方

#### 【やりたい事】
Shift_JISからUTF-8へ変換。
他にも様々な文字コードに対応しています。

文字コードを変換するパッケージでcharset_converterが役立ったので記録として残します。
dart:convertライブラリはUTF-8といった一部のエンコーディングについてはサポートしていますが、Shift_JISについてはサポートしていません。



#### 【環境】
Flutter 3.7.7
Dart 2.19.4

#### 【パッケージ】
charset_converter: ^2.1.1

https://pub.dev/packages/charset_converter



#### 【対応コードの確認方法】
```dart
List<String> charsets = await CharsetConverter.availableCharsets();
```
上記のコードで確認できます。
2023年8月4日時点は以下になります。



[macintosh, x-mac-japanese, x-mac-trad-chinese, x-mac-korean, x-mac-greek, x-mac-cyrillic, x-mac-thai, x-mac-simp-chinese, x-mac-centraleurroman, x-mac-symbol, x-mac-dingbats, x-mac-turkish, x-mac-croatian, x-mac-icelandic, x-mac-romanian, x-mac-ukrainian, utf-16, utf-7, utf-8, utf-32, utf-16be, utf-16le, utf-32be, utf-32le, iso-8859-1, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-9, iso-8859-10, iso-8859-11, iso-8859-13, iso-8859-14, iso-8859-15, cp437, cp737, cp775, cp850, cp851, cp852, cp855, cp857, cp860, cp861, cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936, cp949, cp950, windows-1252, windows-1250, windows-1251, windows-1253, windows-1254, windows-1255, windows-1256, windows-1257, windows-1258, us-ascii, gb18030, iso-2022-jp, iso-2022-jp-2, iso-2022-jp-1, iso-2022-cn, iso-2022-kr, euc-jp, gb2312, euc-kr, shift_jis, koi8-r, big5, x-mac-roman-latin1, hz-gb-2312, big5-hkscs, koi8-u, x-nextstep, ibm037]


#### 【使用方法】
(例)
Shift-JISからUTF-8へ

```dart
final utf8Data = await CharsetConverter.decode('Shift_JIS', contents);
```

contentsの部分に変換したいものを入れれば変換してくれます。


#### 【最後に】

文字コードの変換で困っている方のお力になれれば幸いです。今回紹介したパッケージは様々な文字コードに対応していますので、使ってみて下さい。
一晩寝かせたら臭え問題のかほりが消えてた

# 問題は寝かせるに限るのか
昨日「入力フォームが表示されねえ！」とほざいておりましたが、ふと今になり「"ボタン"を押した際の処理を"ボタン"を指定して組み立ててはいたが"表示場所"ってしっかり指定してたっけ」と思い見返してみたところ、しばしいい加減な場所を指定していたため具体的にしてみたところしっかり表示されました。
![スクリーンショット 2023-08-04 9.14.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512672/3aeff2b2-4961-02ec-2460-b7fdf9a38f57.png)
```js:main.js
//修正前
    const container = document.querySelector(".container-fluid");
    container.appendChild(form);
//修正後
    fileList.appendChild(form);
//補足：fileList = document.getElementById("file-list");
//file-listは事前にHTMLに設けておいた<div class="list-group" id="file-list"></div>です。
```

問題の本質は今もイマイチピンときていませんがやはりレイアウトが被っていたのだろうか。
デザインソフトのように階層わけ？されてるイメージなんですかね。表示されるものが被っている場合はどちらを優先して全面に出すのか、その優先順位への理解が足りていないのが原因なのでしょう。
ブラウザの開発ツールをもっとしっかり活用できていればもっと素早く問題の原因に気づけていたんでしょうねぇ。
下書きしてからコードを書く

# はじめに
エンジニアになって今年で5年？6年目？になるのですが、
1年目から「コメントで下書きをしてからコードを書く」
というやり方で今もなおコードを書き続けているのですが、
結構良い書き方な気がしているので、
今回はそのやり方についてアウトプットしようと思います。

# サンプル要件

やり方を説明するにあたり、下記に書いた要件を満たすコードを書く場合を想定して
話を進めていきます。

* 商品詳細・配送状況を閲覧できる画面であること
* 配送状況は下記によってメッセージを変えること
    * 注文日≠null かつ 配送日=null：「配送手続きをしてください。」
    * 注文日≠null かつ 配送日≠null かつ 配送完了日=null：「配送中です。」
    * 注文日≠null かつ 配送日≠null かつ 配送完了日≠null：「お客さまに商品が届きました。」

# STEP1: とりあえずControllerにやりたいことの大枠を書く

```php
class SampleController extends Controller
{
    public function sample() {
        // 商品の情報を取得

        // 配送状況を判定
    }
}
```

今回だと大枠こんな感じですかね。

# STEP2: より具体的にやりたいことを書き込む

```php
class SampleController extends Controller
{
    public function sample() {
        // 商品の情報を取得
        // 商品テーブル.id = 表示したい商品のIDを取得

        // 配送状況のメッセージを取得
        // 注文日≠null かつ 配送日=nullの時は、「配送手続きをしてください。」のメッセージを付与
        // 注文日≠null かつ 配送日≠nullの時は、配送完了日=null：「配送中です。」
        // 注文日≠null かつ 配送日≠nullの時は、配送完了日≠null：「お客さまに商品が届きました。」
    }
}
```

こんな感じ。
やりたいことの塊ごとに改行して、ブロックをわかりやすくすると、
よりいいかなと思ってます。

# STEP3: Controllerから処理を書きたい場所を呼び出して呼び出し先にコメントをうつす

今回だと
「商品の情報を取得」
「配送状況のメッセージを取得」
の塊をそれぞれServiceに移行していきます。

## Controller
```php
class SampleController extends Controller
{
    public function sample() {
        $sampleService = new SampleService();
        // 商品の情報を取得
        $sampleService->fetchSample();

        // 配送状況のメッセージを取得
        $sampleService->addStatusMessage();
    }
}
```

## Service
```php
class SampleService
{
    /**
     * 商品の情報を取得
     */
    public function fetchSample()
    {
        // 商品テーブル.id = 表示したい商品のIDを取得
    }


    /**
     * 配送状況のメッセージを取得
     */
    public function addStatusMessage()
    {
        // 注文日≠null かつ 配送日=nullの時は、「配送手続きをしてください。」のメッセージを付与
        // 注文日≠null かつ 配送日≠nullの時は、配送完了日=null：「配送中です。」
        // 注文日≠null かつ 配送日≠nullの時は、配送完了日≠null：「お客さまに商品が届きました。」
    }
}
```

こんな感じ！

# STEP4: コード書く！

で、コメントをもとにコードを書いていくという感じです！

コメントでブロックが分けられているので処理が散らばることもないし、
「あ、これ実装してないや」
みたいなことも少なくなるかなと思ってます。

今のところ、あんまりデメリットはないのですが、一応かくと
コメントが大量になるので、開発が終わったらコメントの取捨選択をしていく必要がある感じですかね。


# まとめ

全ての実装をこの方法でやってるわけではないのですが、
処理が複雑になるものほどこの方法で開発してます。
頭も整理できるし、設計の練習にもなるのでおすすめです。

以上！
Qiita アップデートのお知らせ - 2023年 07月

![thumbnail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/521803ff-e55d-ba9f-3da9-efbdb8abdfd7.png)


## はじめに
Qiitaでは、エンジニアのみなさんからの声をもとに、日々開発を続けています。
この記事では、2023年 07月にリリースした内容を紹介します。

Qiitaでアップデートやバグ修正をリリースしたら、[リリースノート](https://qiita.com/release-notes)、[Qiita 公式 Twitter](https://twitter.com/Qiita)、[Qiita Blog](https://blog.qiita.com/)でお知らせしています。

また、Qiitaへの質問や機能の要望などがありましたら、[Qiita Discussions](https://github.com/increments/qiita-discussions) へご投稿ください。

## 質問フィードページをアップデートしました
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/26d24eb5-7474-e56f-aa6f-531b8bea56c5.png)
*2023年 07月11日 リリース*

質問者、回答者どちらにとっても使いやすいフィードを目指し、質問フィードページをアップデートをしました。
アップデートに伴い、質問フィードの種類を以下のように変更しました。
それぞれのフィードはフォローしているタグで絞り込むことが可能です。
[タグのフォロー方法についてはヘルプをご覧ください。](https://help.qiita.com/ja/articles/qiita-question-feed)

- [すべて](/question-feed)
   - 全ての質問を新着順に表示します
- [回答募集中](/question-waiting-answers)
   - クローズしていない質問をランダムに表示します
- [未回答](/question-no-answers)
   - 回答がついておらず、クローズしていない質問を新着順に表示します
- [クローズ](/question-closed)
   - クローズ済みの質問を新着順に表示します

[質問フィードのヘルプページはこちら](https://help.qiita.com/ja/articles/qiita-question-feed)


## エディタのデザインを新しくしました
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/dc431cd4-704a-1137-ef2d-ca6d9d4ae73c.png)
*2023年 07月11日 リリース*

エディタのデザインを新しくしました。
ヘッダーとフッターに表示されていた要素をまとめ、より執筆に利用できるエリアが広がるようにしました。

変更前|変更後
-|-
![ヘッダーとフッターが表示されています。ヘッダーにはQiitaのロゴや検索フォーム、ユーザーメニューなどがあり、フッターには下書き保存や公開設定のボタンがあります。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/5f1a4f43-d363-9d7b-39fa-a412e9db4851.png)|![Qiitaのロゴとユーザーメニューにアクセスするボタンと下書き保存や公開設定のボタンがヘッダーにまとまっています。](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/330c095d-06ec-0ea8-7e0b-a2f7d95f1e37.png)

## 質問検索機能をベータ版として公開しました
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88/9dad9406-6033-8fcd-5c1f-665ace0c7824.png)
*2023年 07月18日 リリース*

質問検索機能をベータ版として公開しました。
記事検索ページの左サイドバーから、[質問検索ページ](/question-search?q=React)に遷移できます。


## 数式の表示に使っているライブラリ（MathJax）のバージョンアップを行いました。
*2023年 07月6日 リリース*

数式の表示に使っているライブラリ（MathJax）のバージョンアップを行いました。
これにより、様々なバグの解消、エディタでのちらつき解消、新たな拡張の追加などの改善ができました。

同時に、いくつかの記法に関して非互換が発生します。

詳しい内容は[Qiita Blog](https://blog.qiita.com/update-math-jax-v3/)をご確認ください。


## ブラウザバック等でエディタに戻ったときにも、最新の下書きが表示されるようになりました
*2023年 07月21日 リリース*

今までは、記事と質問のエディタからページ遷移し、ブラウザバックをした場合、古い下書きが表示されてしまっていました。
下書きには自動保存機能があるのですが、意図しないページ遷移によって古い内容で上書きされてしまうことがありました。

今回、エディタに戻ったときに最新の下書きが表示されるようになり、意図せずに上書きされてしまうことが起きにくくなりました。

## Mermaidのバージョンを8.14.0から10.2.4に変更しました
*2023年 07月26日 リリース*

Mermaidのバージョンを8.14.0から10.2.4に変更しました。
これにより新たに様々な記法が使えるようになりました。
またv8時点でExperimentalだったgitGraphを使っている場合、記法が大きく変更されているのでご注意ください。

詳しくは[Mermaidのリリースノート](https://github.com/mermaid-js/mermaid/releases)をご覧ください。
Db2 for iのカラム名その他の最大長

Db2 for i のカラム名、スキーマ名、その他名前の最大長の一覧はこちらに記載があります。
(Db2 for i) SQL の制約
https://www.ibm.com/docs/ja/i/7.5?topic=reference-sql-limits

■最大長をいくつか拾ってみると、
スキーマ名　　　128
サーバー名　　　18
非修飾の表名、ビュー名 128　
※ここで非修飾、とはライブラリー名を除いた最大長の意味
XMLパス名　　　128
XMLエレメント名、属性名、等　　　1000
JSONパス名　　　128

■数値の制約　というのも記載があり、
SMALLINTの最小値/最大値　-32768 / 32768
INTEGER（整数）の最小値/最大値  -2147483648 / 2147483647
10進数の精度の最大値　　　　63

■テーブル関連
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/1316344d-8764-7d1d-4202-0529f4a9802e.png)

■JSON/日付時刻
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/0df05456-4b37-f01f-a6fa-21c89e87728e.png)

■DBMS
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/9efc8a68-905a-8140-23d2-c3bfa76369f0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/289b8ea6-c910-1930-5952-2d43fde7a8b4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/8f17b392-2117-84d1-e657-2a8997150e44.png)



などなどです
LangChain の DocumentLoader のように HTMLファイルの一部を読み取っていくサンプル

# 概要
- LLM で RAG などをしたいため、HTML ファイルを読み取りベクトルデータベースに保存したい
- LangChain で HTML の DocumentLoader が使えるが、HTML の一部を抽出することができない
    - https://python.langchain.com/docs/modules/data_connection/document_loaders/html
    - セレクタ、XPath、id 指定など
- 代替手段のサンプルを提供

# 手順
- BeautifulSoup を使って HTML ファイルの一部を読み取る
- LangChain の Document クラスを手動で生成する

# サンプルスクリプト
```python
import os
from pathlib import Path
from bs4 import BeautifulSoup
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.docstore.document import Document

# 特定ディレクトリのサブディレクトリも含むファイル一覧を取得
html_dir = Path("どこかのディレクトリ")
html_files = list(html_dir.glob("**/*.htm"))

# HTML内のデータを分割する用のSplitterを用意
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=0)

all_documents = []
for p in html_files:
    # HTMLファイルを BeautifulSoup で読み込み
    with open(p, "r", encoding="UTF-8") as f:
        soup = BeautifulSoup(f)

    # HTMLの一部を取得(今回は id 指定)
    content = soup.find(id="main-content").text
    # タイトルを取得(今回は h1 タグのテキスト)
    title = soup.find("h1").text

    # langchain の DocumentLoader を使わず、自前で Document を作成
    # メタデータにファイルのパス、タイトルを設定
    doc = Document(page_content=content, metadata={"source": p, "title": title})

    # documentをsplitterで分割してリストに追加
    splited = text_splitter.split_documents([doc])
    all_documents += splited

# LangChain のサンプルを参考にベクトル化するなど
embeddings = OpenAIEmbeddings(deployment="text-embedding-ada-002")
db = Chroma(persist_directory="_vecorstore", embedding_function=embeddings)
for doc in all_documents:
    doc.metadata["source"] = str(doc.metadata["source"])
    db.add_texts([doc.page_content], [doc.metadata])

```
Installing Displaylink Device Driver on RHEL8

<H1>Displaylink (ThinkPad Dock series) driver install</H1>

- Adding epel repository
```
$ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
```

- Download Displaylink driver from github
 https://github.com/displaylink-rpm/displaylink-rpm/releases

- Install Displaylink Driver in CUI mode
Before installing the driver you should make sure following points 
  - Disable secureboot in BIOS setup
  - You must install the driver in CUI mode. If you install in GUI mode, machine might be hung.
 
```
$ sudo dnf centos-stream-stream8-displaylink-1.13.1-2.x86_64.rpm
```
If you want to change GUI(runlevel 5) to CUI(runlevel 3)
```
# init 3
```
After the install, you can back to GUI
```
# init 5
```

<B>Note:</B>
SecureBoot must be disabled. If it is enabled, displaylink does not work.
Ningbo Investment Casting Co., Ltd

Ningbo Investment Casting Co., Ltd, was founded in 1983, has been focusing on casting and machining for over three decades. It’s located in Ningbo, is consisted of a Lost-wax casting foundry (also called investment casting and precision casting) and a machining shop. It occupies 95000㎡. More than 300 employees are working here, including 30 highly-professional engineers and well-trained technicians. We consider our employees as an asset and it is this asset that provides us the capability to offer our customers products of quality in a short lead time.
wslでelixir その32

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題、やってみた。

# 練習問題
websocket serverでじゃんけんを返せ。
0- グー、1-チョキ、 2-パー 
portは、50002
clientは、neosvr

# 写真

![2023-08-03 23.36.04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8db6eff8-c591-7430-9272-6adbc7349eda.jpeg)

# サンプルコード

```
defmodule Janken do
	def hand(c) do
		cond do
		c == 0 ->
			"グー"
		c == 1 ->
			"チョキ"
		c == 2 ->
			"パー"
		:else ->
			"うそ"
		end
	end
	def judge(a, b) do
		cond do
		a == b ->
			"あいこ"
		a == 0 && b == 1 ->
			"あなたの勝ち"
		a == 1 && b == 2 ->
			"あなたの勝ち"
		a == 2 && b == 0 ->
			"あなたの勝ち"
		a == 0 && b == 2 ->
			"あなたの負け"
		a == 1 && b == 0 ->
			"あなたの負け"
		a == 2 && b == 1 ->
			"あなたの負け"
		end
	end
	def pon(a) do
		res = ""
		{a, _} = a
			|> Integer.parse()
		res = res <> hand(a) <> "と"
		b = 0..2 
			|> Enum.random
		res = res <> hand(b) <> "で、"
		res = res <> judge(a, b)
		res
	end
end

defmodule Janken.Server do
	alias ElixirSocketTesting.ClientAgent
	def start(port \\ 50002) do
		ClientAgent.start_link
		server = Socket.Web.listen! port
		loop(server)
	end
	def loop(server) do
		client = server
			|> Socket.Web.accept!
		client
		|> Socket.Web.accept!
		ClientAgent.add(client)
		Task.async(fn ->
			recv(client)
		end)
		loop(server)
	end
	def recv(client) do
		case client |> Socket.Web.recv! do
		{:text, message} ->
			res = Janken.pon(message)
			broadcast({:text, res})
			recv(client)
		{:close, _, _} ->
			ClientAgent.remove(client)
		other ->
			IO.inspect other
		end
	end
	def broadcast(packet) do
		ClientAgent.all
		|> Enum.each(fn client ->
			Socket.Web.send(client, packet)
		end)
	end
end

```

以上。
ループ処理を野球部に説明してみた

おはようございます！
今日はループ処理を野球部に説明してみた、というテーマの記事です。
この記事を読むことで、ループ処理の基本的な使い方と、それがプログラム内でどのように機能するのかを理解できるようになることを目指します。


### ループ処理とは
ループ処理とは、同じ処理を繰り返し行うことを指します。同じ処理のコードを何度も書かなくて良くなるというメリットがあります。
例えば、PP10本という練習メニューをループ処理有りと無しに分けて書いてみるとこんな感じです。

#### ループなし
```
ダッシュする  // 1本目
ダッシュする  // 2本目
ダッシュする  // 3本目
ダッシュする  // 4本目
ダッシュする  // 5本目
ダッシュする  // 6本目
ダッシュする  // 7本目
ダッシュする  // 8本目
ダッシュする  // 9本目
ダッシュする  // 10本目
```

#### ループあり
```
for (let i = 1; i <= 10; i++) {
   ダッシュする；
}
```

すごくスッキリしましたね！
他にも、野球は表と裏の攻撃を９イニング繰り返しますし、先輩にだる絡みされている時に自動応答で返事をしている時もループ処理を行っていると言えるかと思います。

### 実際のコードは？

それでは、実際のコードを見てみましょう。今回はJavaScriptのコードを使います。このコードは、1から10までの数値を使って、それぞれの数値の二乗を計算し、結果を表示する機能を持っています。

```
function calculate() {
  for (let i = 1; i < 10; i++) {
    const newResult = `${i} x ${i} = ${i * i}`;
    results.textContent += `${newResult}\n`;
  }
  results.textContent += "\n完了!";
}
```

このコードの最初の部分は、関数の定義です。関数とは、特定の処理をまとめたもので、この場合はcalculateという名前の関数を定義しています。関数内部にはfor文があり、これがループ処理を行う部分です。for文の中には3つの部分があります。最初の部分`let i = 1`は、ループの初期値を設定しています。次の部分`i < 10`は、ループを続ける条件を設定しています。最後の部分`i++`は、ループの各ステップで行う処理を設定しています。この場合、iの値を1ずつ増やしています。

ループの中には、新しい結果を計算し、それを表示する処理が含まれています。`${i} x ${i} = ${i * i}`は、iとiの二乗を計算し、その結果を文字列として表示します。そして、その結果をresultsという変数に追加しています。

このように、ループ処理は一連の処理を繰り返し行うための強力なツールです。野球のトレーニングのように、同じ流れを何度も繰り返す場合には、ループ処理が非常に役立ちます。


### まとめ
今日のまとめとして、以下の3つのポイントです。

1. ループ処理は、同じ処理を繰り返し行うためのツールです。
2. for文を使うと、特定の条件下で処理を繰り返すことができます。
3. ループ処理は、一連の処理を効率的に行うための強力なツールです。

以上が今日の内容です。
もし記事が役立ったと思ったら、ぜひいいねやフォローをお願いします。
これからも、プログラミング初心者の皆さんが理解しやすいような記事を書いていきますので、お
楽しみに！

それでは、今日も学習をはじめていきます！
wslでelixir その31

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題、やってみた。

# 練習問題
websocket serverで湯婆婆を返せ。
portは、50002
clientは、neosvr

# 写真

![2023-08-03 22.53.06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e9eb84f6-eeff-5dd4-fb86-e274d5274606.jpeg)

# サンプルコード

```
defmodule Yubaba.Server do
	alias ElixirSocketTesting.ClientAgent
	def start(port \\ 50002) do
		ClientAgent.start_link
		server = Socket.Web.listen! port
		loop(server)
	end
	def loop(server) do
		client = server
			|> Socket.Web.accept!
		client
		|> Socket.Web.accept!
		ClientAgent.add(client)
		Task.async(fn ->
			recv(client)
		end)
		loop(server)
	end
	def recv(client) do
		case client |> Socket.Web.recv! do
		{:text, message} ->
			res = Yubaba.say(message)
			broadcast({:text, res})
			recv(client)
		{:close, _, _} ->
			ClientAgent.remove(client)
		other ->
			IO.inspect other
		end
	end
	def broadcast(packet) do
		ClientAgent.all
		|> Enum.each(fn client ->
			Socket.Web.send(client, packet)
		end)
	end
end


```

以上。
くらしTEPCO

東京電力のサイトを久しぶりに見てみたら、結構ちゃんと出来てました。

以前は日ごとのグラフが無かったのですが、ちゃんと出来てます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/69666a65-5cfa-e995-efa8-be0c4f8516b7.png)

Wi-SunのBルートで取ってるデータのグラフです。

![filename(39).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/dc387847-5227-5858-4ece-ed89de97770a.png)

データも一致しています。(countはデータ取得回数です。結構失敗してるようなので、グラフで確認できるようにしてます。10分おきに取得しているので、全回成功すれば144です。)

時間別のグラフもあります。

一時期細かい情報は有料サービスになっていたような記憶がありますが、今は誰でも見れるようです。

自分の作ったおうちモニターとほぼ同等です。これだけ出来ればわざわざBルートを使う必要も無いかもしれませんね。

日ごとの使用量を確認すると、何が大きく使用しているかが把握でき、節電の参考になります。

死んだきで節電して我が家は7月も3千円台でした。よいこはまねしないでね。
wslでelixir その30

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題、やってみた。

# 練習問題
websocket serverで九九を返せ。
portは、50002
clientは、neosvr

# 写真

![2023-08-03 22.15.39.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b762a33b-f31f-dcef-62c6-28b84e9b62ae.jpeg)

# サンプルコード

```
defmodule Kuku.Server do
	alias ElixirSocketTesting.ClientAgent
	def start(port \\ 50002) do
		ClientAgent.start_link
		server = Socket.Web.listen! port
		loop(server)
	end
	def loop(server) do
		client = server
			|> Socket.Web.accept!
		client
		|> Socket.Web.accept!
		ClientAgent.add(client)
		Task.async(fn ->
			recv(client)
		end)
		loop(server)
	end
	def recv(client) do
		case client |> Socket.Web.recv! do
		{:text, message} ->
			res = Kuku.str
			broadcast({:text, res})
			recv(client)
		{:close, _, _} ->
			ClientAgent.remove(client)
		other ->
			IO.inspect other
		end
	end
	def broadcast(packet) do
		ClientAgent.all
		|> Enum.each(fn client ->
			Socket.Web.send(client, packet)
		end)
	end
end

```

以上。