OmniAICreator/Qiita-1.07M huggingface dataset:
Web系エンジニア転職が成功する人の特徴 10選


こんにちは。[Happiness Chain](https://happiness-chain.com)を経営している[ゆうだい](https://twitter.com/yudai_on_rails)です。

この記事は [Happiness Chain Advent Calendar 2023](https://adventar.org/calendars/9414) 9日目の記事です。

## はじめに
未経験・SES・SIerからWebエンジニアを目指して勉強している人たちを300人以上見てきました。その中で、うまくいく人とそうで無い人の特徴、パターンがわかってきたので共有します。Web系に転職したい人はぜひ最後まで読んでいただけると幸いです。

## 1. 英語から逃げない
英語は苦手だから全て翻訳に頼ろうというマインドの人でうまくいっている人は少ないです。エンジニアなら英語から逃げては絶対にダメです。英語ができない人は変数の命名が不自然だったりします。コードレビューではそんなしょうもないことを指摘したくないです。命名は難しいですが、必要最低限の英語力(高校卒業レベル)は絶対に欲しいです。英語から逃げるのはもうやめて、真正面から向き合いましょう。

## 2. 諦めが悪い
諦めが悪い人は何事においても強いです。成果が出るまで継続するというマインドが重要です。
数時間エラーにハマったり、設計に悩んだり、初学者のときは苦労の連続です。今まで部活や勉強を頑張ってきた経験がある人は、それを乗り越える忍耐力を持っているので挫折しません。損切りは大事なのですが、粘ることも大事です。最初のうちはうまくいかなくて当たり前です。エラーにハマってもすぐ投げ出さずに、時間をかけて戦いましょう。

## 3. 自分の成長を楽しんでいる
人と比べず、常に過去の自分と戦っているイメージです。その方が挫折することなく、勉強を楽しく継続できます。個人差は大きいので、人と比べて落ちこむくらいならば、そもそも比較しない方がいいでしょう。競争相手は常に昨日の自分です。できるようになったことを毎日、毎週書き出して、自分の成長を楽しみましょう。

## 4. 同じ目標を持つ友達を作るのがうまい
学生だと、自然に友達はできましたよね。でも社会人になるとそうはいきません。積極的に自分から行動しないと友達はできませんよね。一人で勉強を継続するのは大変です。勉強会に参加したり、何らかのコミュニティに入ったり、スクールに通ったりして友達を作る努力をしましょう。無料コミュニティだと質が悪く、マルチの勧誘が混ざっていたりするのでご注意ください。


## 5. 素直で謙虚にプロの意見を聞く
「Linuxっていらないですよね？」 みたいな反論をせず、素直にプロの意見に従う人がうまくいっています。郷に入っては郷に従えです。素直な人は本当によく伸びます。ビジネスの基本は丸パクリからです。オリジナリティを加えるのは基礎をガッツリ固めてからです。謙虚で素直に先生のアドバイスに従いましょう。

## 6. 勉強代をケチらない
99%の日本人は勉強代をケチります。僕は脳のネジがいい感じにぶっとんでいるので、ノーグダで160万のスクールに入会したりします。お金があるからスクールに通うのではなく、スクールに通うからお金持ちになれるのです。お金がないグダを発動してうまくいっている人を見たことがありません。余談ですが、おさるさんのマーケティングスクールは神です。審査制なので優秀な人しか入れないと思います。

## 7. ノウハウコレクターにならない
情報が溢れている時代です。次から次へとYouTubeやXを徘徊し、結局行動に移せない人が多いです。ノウハウコレクターは今すぐやめましょう。信じるのは一人だけ、多くても3人でいいと思います。一人の言うことを全て実践すれば、（その人がまともなら）必ず成果が出ます。大事なのは「この人についていく！」と覚悟を決めること。いろんな情報発信者のいいとこ取りは良くないです。自分が信じた一人についていき、彼の言うことは全て実践しましょう。

## 8. アウトプットしている
Qiitaの記事やブログ記事も職務経歴書に書きます。ポートフォリオ＝アプリだと思っている未経験の人は多いですが、アウトプットした記事も立派なポートフォリオになります。マサカリや失敗を恐れず、積極的にアウトプットしてきましょう。

## 9. 失敗を恐れず行動する
失敗は必要経費です。そこから学び、同じミスを犯さないようにすれば、失敗には大きな価値があります。もはや失敗という言葉がナンセンスですね。麻雀で一発でツモれないのと同様に、ハズレを潰す作業は必須です。ハズレを一つずつ潰していけば、いつか当たりに辿り着きます。失敗を恐れず、挑戦し続けるマインドが重要です。


## 10. 言い訳をしない
言い訳なんて無限にできます。人間は自分を正当化したい生き物です。そうやって、自分で言い訳を作り、なんとか自己肯定感を保っている人が大勢います。僕からすれば、正論で全て論破できます。まあ論破したところでまた言い訳の反論が返ってくることがありますが、そういう人間とは関わらないようにしています。

- お金がない ← 借りれば？
- 時間がない ← 労働をやめれば？
- 結婚しているから　← 結婚を選んだのは自分でしょう？ 離婚すれば？
- もう歳だから ← 今まで何してたの？ そんなことを今更嘆いても仕方なくない？

強いビジネスマンは言い訳なんてしません。たとえそれが真実だったとしても、そんなことを愚痴っても意味がないからです。言い訳するのは今すぐにやめて、とにかく行動に移しましょう。

## さいごに
「Web系エンジニア転職が成功する人の特徴 10選」というタイトルで執筆しましたが、エンジニア転職以外にも重要なマインドが多くあります。未経験転職は大変ですが、やることをきっちり1年スパンで継続すれば必ず成功します。応援しています！
GET・POST使い分け

## 概要
- 理解の確認として、振り返りもかねてGET、POSTの使い分けをまとめる

## GET・POST使い分け
### 参照の場合
>GET メソッドは、［ 現在の，ターゲットリソース用に選定される表現 ］を転送するよう要請する。 **GET は、情報を検索取得する主たる仕組みであり，ほぼすべての処理能 最適化の力点が置かれる所である。** よって、誰かが［ HTTP を介して識別できる何らかの情報を検索取得する ］ことについて話すとき，たいていは GET 要請を為すことを指している。

- GETメソッドは、参照のみに用いる
- GETメソッドは副作用がないことが期待される

### 秘密情報の場合
>9.4. URI 内の敏感な情報の開示
URI は、セキュアなリソースを識別するものであっても，［ 共有され, セキュア化されないもの ］になるように意図されている。 URI は、［ ディスプレイに示される／ ページの印刷時に各用紙に刷られる／ 様々な未保護なブックマークリスト内に格納される ］ことが多い。 **したがって，［ 敏感な／個人識別可能な／開示されるリスクがある ］情報を URI に内包することは、賢明でない。**
サービスの作者は、**［ GET に基づくフォームによる，敏感なデータの提出 ］は避けるべき.である** — 何故なら、そのデータは， request-target 内に置かれることになるので。 多くの既存の［ サーバ／プロキシ／UA ］は、 **request-target を［ 第三者主体から可視になり得る所 ］に，ログしたり, 表示する。** そのようなサービスは、**代わりに POST に基づくフォームによる提出を利用するべき.である。**
Referer ヘッダは，要請を生じさせた文脈について ターゲットサイトに伝えるので、**［ 参照元リソースの URI ］内に見出され得るような［ 利用者の直前の閲覧履歴についての情報, その他の個人情報 ］を露わにする可能性がある。** Referer ヘッダに対する制限は、その定義に述べたように，そのセキュリティの考慮点の一部に取り組む。

https://triple-underscore.github.io/RFC7231-ja.html#section-9

- 秘密情報の送信にはPOSTメソッドを用いる
    - リソースの取得以外の動作、追加・更新・削除などの作用がないことを示している。
- Refererヘッダやrequest-targetヘッダに置くことで、第三者から見ることができてしまう

### 送信すべきデータ量が多い場合
https://support.microsoft.com/ja-jp/topic/internet-explorer-%E3%81%AE-url-%E3%81%AE%E6%9C%80%E5%A4%A7%E9%95%B7%E3%81%AF-2-083-%E6%96%87%E5%AD%97%E3%81%A7%E3%81%99-174e7c8a-6666-f4e0-6fd6-908b53c12246

https://qiita.com/_matuzaki/items/70fb639f7ed7463f9943

- ブラウザ上の制限があるため、多い場合はPOSTを利用する

### まとめ
- データを参照するものはGETを利用する
- 参照以外のことを行う場合は、POSTやDELETEなど別のメソッドを利用する
- 第三者に公開していけない情報が含まれる場合は、POSTを利用する
- データが多い場合も、POSTを利用する

## 参考図書
**体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践 単行本 – 2018/6/21**

https://amzn.asia/d/ftKt5wT

## 参考web

https://qiita.com/kanataxa/items/522efb74421255f0e0a1

https://apidog.com/jp/blog/get-post-difference/


## まとめ
基本的に問題なく利用していたが、**体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践 単行本 – 2018/6/21**を利用して学習していく中で、基礎の部分をさらうべきであると考えまとめた。
データ量に関しては知らなかったため、早めに学ぶことができてよかったと思う。
ExpressでUTCをJSTに変換する

# 目的
・JSTとUTCについて知る
・Node.jsでUTCからJSTに変換する方法についてまとめる

# 現象
AngularMaterialのdatepickerを使用して、以下のように日付を選択して、取得した日付データを確認する。
![スクリーンショット 2023-12-08 9.28.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458671/e2eed4d4-0388-26cd-6f9a-46bb620464ad.png)

![スクリーンショット 2023-12-08 9.28.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458671/e5dd3c29-9611-11c9-e14c-90c56361518e.png)

このようにJSTで表示される。ただ、これをNode.js+Expressで実装されたAPIに送信すると、以下のように、UTCで表現される。
![スクリーンショット 2023-12-08 9.28.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458671/017b5cec-6860-e8da-88dd-92964431aadb.png)

UTCとJSTについてはこちらの記事にまとまっている。

https://linuc.org/study/knowledge/333/


# 原因
この現象が起きる原因としてはDateオブジェクトがクライアントとサーバで異なるタイムゾーンで解釈されるためである。Angularではブラウザのローカルタイムゾーンに基づいているので、画面上で選択した値になっているが、Node上ではUTCに変換されるためこのような現象が起きている。

この現象はChromeで確認したが、Chromeで利用されているタイムゾーンはOSのタイムゾーン情報が反映されているらしい。

https://did2memo.net/2021/01/29/chrome-how-to-set-timezone/#chrome

# 対処法
対処法としては以下のようなことが考えられる。
 ## 時差を補正する
 UTCに変換されたデータをExpress側でJSTに変換する。
```typescript
convertUtcToJst(date: Date):string => {
  // UTC形式の日時を文字列に変換
  const utcDateString: string = date.toISOString();

  // UTC形式の日時文字列からUTCのDateオブジェクトを生成
  const utcDate: Date = new Date(utcDateString);

  // JST（日本標準時）のオフセットを計算（9時間 * 60分）
  const jstOffset = 9 * 60;

  // UTCのDateオブジェクトにオフセットを加算してJSTのDateオブジェクトを生成
  const jstDate: Date = new Date(utcDate.getTime() + jstOffset * 60000);

  // JSTのDateオブジェクトをISO 8601形式の文字列に変換
  const jstDateString: string = jstDate.toISOString();

  // JST形式の日時文字列を返す
  return jstDateString;
}

```
JSTはUTCよりも9時間進んでいるのでオフセットを計算して取得したUTCの値に加算している。またJSTに変換後にISO8601形式に変換している。ISO8601形式とは、日付と時刻の表記に関する国際規格のことで以下のページで詳しく説明されている。
今回はこちらの方法で対処した。

https://zenn.dev/yass97/articles/2b5dcd5499ab07

 ## サーバ側のタイムゾーンをJSTに変換する
 Node.jsのタイムゾーンを JSTに変換する方法もある。ただ、今回使用しているOSはWindowsでWindowsでは環境変数を編集することで特定のアプリケーションのタイムゾーンだけを変更するということができないので、今回はこの対応は行わなかった。MacやLinuxを使用して、なおかつ、プログラムの至る所でJSTへの変換処理を行なっている場合にはこちらの対応策を検討してもいいかも知れない。

 https://zenn.dev/dora1998/articles/node-process-env-tz#%E3%81%9D%E3%82%82%E3%81%9D%E3%82%82-windows-%E3%81%AB-tz-%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AF%E3%81%AA%E3%81%84
UWSCRの新機能：非同期処理

Taskという仕組みが追加され、async/awaitができるようになりました。命名に関してはC#でTaskと呼んでるのでそれでいいかな、という感じでやりました。

# 組み込み関数による非同期処理

`Task()`関数でユーザー定義関数を非同期に実行し、Taskオブジェクトを返します。非同期実行された関数の結果を得るには`WaitTask()`を実行します。

```php
function func()
    print "タスク処理開始"
    sleep(1)
    print "タスク処理中"
    sleep(1)
    result = "タスク処理終了"
fend

t = task(func) // task関数に非同期実行する関数を渡す
print "func関数が非同期実行されています"
print waittask(t) // waittask関数にタスクオブジェクトを渡すと終了を待って結果を返す
```

```console:出力
タスク処理開始
func関数が非同期実行されています
タスク処理中
タスク処理終了
```

# async/await

`async`キーワードを付けることで非同期関数を定義できます。

```php
async function func()
    print "タスク処理開始"
    sleep(1)
    print "タスク処理中"
    sleep(1)
    result = "タスク処理終了"
fend
```

`await`キーワードで非同期関数の終了を待ちます。

```php
print await func()
```

非同期関数はTaskオブジェクトを返すため、`WaitTask()`関数も利用可能です。

```php
t = func()
print waittask(t)
```

Taskオブジェクトを返す関数であれば`await`できるため`Task()`関数もawaitできます。

```php
function func()
    print "タスク処理開始"
    sleep(1)
    print "タスク処理中"
    sleep(1)
    result = "タスク処理終了"
fend

print await task(func)
```

:::note warn
#### 世界一雑なasync/await実装

一応非同期に動くよね、という程度の実装で非同期処理の実装として正しいのかどうか？もよくわからずやっています。使い道も想定されておらずちゃんと使えるかどうかも実はわかりません！なにか不都合や改善点などありましたら[github](https://github.com/stuncloud/UWSCR/issues)でご一報ください。
:::

# Promise対応

UWSCRのブラウザ操作機能でJavaScriptオブジェクトを得られるのですが、それが`Promise`だった場合に`WaitTask()`関数で終了を待って結果を得られるようになっています。また、JavaScriptの非同期関数を`await`できます。

```php
// ブラウザ起動または再接続
chrome = BrowserControl(BC_CHROME)
tab = chrome[0]
tab.navigate("https://example.com")

// 非同期関数を作る
func = tab.eval("async (n) => n * 2;")

// 非同期関数を実行してPromiseを得る
promise = func(5)
// WaitTask()で終了を待って値を得る
print waittask(promise) // 10

// awaitもできる
print await func(10) // 20
```


:::note info
ブラウザ操作はUWSCR新機能の中でも目玉となるすごいやつです。詳しくは12/24の記事で解説します！
:::
WebのUIコンポーネントの再利用性を下げた例についていくつか紹介

# 概要

WebフロントエンドにてUIコンポーネントを作り直す機会に多く恵まれ、その中でどういうコンポーネントにすると再利用性が下がるのかを発見できたので紹介したい。

以下、React, JSXを利用しているものとする。

## z-indexを利用したコンポーネント

`z-index` を利用するとコンポーネントに閉じない影響を他コンポーネントに与える。
どこかのコンポーネントで `z-index` を利用するとそのコンポーネントを利用しようとしたときに、常に `z-index` を考慮した実装に気を付けなければならない。

`stylelint` や変数化などして無策に利用するのは避けたい。
floating-uiで`z-index`を利用しないのもオススメ。
<https://floating-ui.com/>

## 1以上の数のtabindexを利用したコンポーネント

`tabindex` で1以上の数を設定すると、コンポーネントに閉じない影響を与える。z-index同様に、コンポーネントを利用するときに注意が必要だ。さらには、タブキーによるフォーカスでユーザーに違和感を与えない試行錯誤が必要にもなる。

eslintで避けられるので設定するのがオススメである。
<https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/tabindex-no-positive.md>

## 左側が前面で重なった表現を利用したコンポーネント

通常、重なりをそのままcssで実装しようとすると、`position: relative` や `absolute` を利用することになる。その時の表現としては、右側が前面になるような見た目のUIになる。
これに対して、左側が前面になるようなUIを表現するには、`z-index` をそのまま利用するか、左側に配置したいUIを右側に配置したいUIよりも、敢えて下に記入して `position` を指定する方法がある。

```html
<div>右側後面</div>
<div>左側前面</div>
```

`z-index` は先に述べたように利用しないことが望ましい。ただ、左側前面になるものを右側後面になるものよりも下に書くと、タブキーによるフォーカスが逆転する（右側後面→左側前面の順になる）。
`tabindex`を付けて対応することもできるが、`tabindex` はコンポーネントに閉じない影響をあたえるため、この方法も望ましいといえない。

かがんさんの記事で、親に`z-index: 0`を付けることでこの問題を回避することができることを知った。
<https://zenn.dev/kagan/articles/1aa466bb6ef8eb>

## 複数のコンポーネントを含む全体がクリック可能なコンポーネント

イメージは下記の状態である。`ClickableComponent` には`button`が利用されいると仮定し、`Component` の中に `a`や`button`があった場合は、HTMLの仕様的に違反した書き方になる。インタラクティブなタグの中にはインタラクティブなタグを入れてはいけない。

<https://www.w3.org/TR/2011/WD-html5-20110525/the-button-element.html>

```jsx
<ClickableComponent>
  <Component />
</ClickableComponent>
```

この問題を回避する方法として、`ClickableComponent` が、`a`や`button`などを利用せずに、`div`や`span`を使いクリック可能にする。

```jsx:ClickableComponent
<div onClick={}>
  {children}
</div>
```

ただ、これにも問題がある。クリック可能な要素としてbuttonタグを利用した時と比べて、タブキーによるフォーカスを充てられるようにとか、role設定とか、buttonじゃないものに対してbutton的に振舞わせる努力が必要だ。divにblur関数が無くエスケープでfocusを外す機構の実装は諦めた。

## まとめ

いくつかのWebのUIコンポーネントとして再利用性を下げる具体的な事例を紹介した。
再利用性を高めるためには、仕様の検討するときにいずれのパターンを避け、できるだけ回避したい。
ただ、知識や実装力が高ければ、仕様で回避せずとも何とかなるかもしれない。
ねぇ、なんでデリゲートは参照型なの？

普通に値型にできる気がする。

参照型にしてもGCの仕事増やすだけじゃん。

```CSharp
public readonly unsafe struct ValueAction<T>
{
    readonly delegate* managed<object, T, void> _d;
    readonly object _i;

    private ValueAction(delegate* managed<object, T, void> d, object i)
    {
        _d = d;
        _i = i;
    }

    public void Invoke(T value) => _d(_i, value);

    public static ValueAction<T> Get(Action<T> from)
    {
        var method = from.Method;
        if (method.IsStatic) throw new ArgumentException();
        return new((delegate* managed<object, T, void>)method.MethodHandle.GetFunctionPointer(), from.Target);
    }
    public static ValueAction<T> Get<TTarget>(delegate* managed<TTarget, T, void> pointer, TTarget target) where TTarget : class
    {
        return new((delegate* managed<object, T, void>)pointer, target);
    }
}
```

当然静的メソッドはカリー化を挟む必要があるし、マルチキャストも出来ないけど、シンプルな用途ならこれで十分。

---

https://ufcpp.net/study/csharp/functional/miscdelegateinternal/

この記事によるとデリゲートは参照型の上に必要最低限のメンバの二倍のメンバを持っているらしく、ますます意味不明。(もちろん用途は理解できるが、あえて標準的に装備する必要があるほどのものかは謎)
落合陽一式論文要約フォーマットを使って論文をまとめてみる

アドベントカレンダー7日目ということで、落合陽一式論文要約フォーマットをベースにして論文を読んでいきたいと思います。

## 落合陽一式論文要約フォーマットって？
[こちら](https://www.slideshare.net/Ochyai/1-ftma15)のリンクにあるスライドで紹介されている論文を読んでまとめるためのフォーマットです。具体的には以下の手順とフォーマットでまとめていくものです。

1. 論文をAbstract → Conclusion → Experiments → Related workの順に読む。
2. 以下の項目を埋めて一枚のスライドを作る。
    * どんなもの？
    * 先行研究と比べてどこがすごい？
    * 技術や手法のキモはどこ？
    * どうやって有効だと検証した？
    * 議論はある？
    * 次に読むべき論文は？

## 実際にやってみる
#### 今回読む論文
わたしはニューラル機械翻訳(NMT)についての研究をしているので、[Incorporating BERT into Neural Machine Translation](https://openreview.net/forum?id=Hyl7ygStwB)という論文を読んでみることにしました。
#### 手順
先述した読み方とフォーマットをベースにして、以下のやり方で実践します。

1. 論文をAbstract → **Introduction** →Conclusion → Method → Experiments & Results → Related Workの順に読む。
2. 以下の項目を埋めてまとめる。
    * どんな論文？
    * 先行研究と比べてどこが凄い？
    * 技術や手法のポイントは？
    * どうやって有効だと検証した？
    * 議論はある？
    * 次に読むべき論文は？
    * 自分の意見、ideaは？

1\.でintroductionをConclusionの前に持ってきたのは、論文で使われているabbreviationを把握しておきたかったからです。その分野についてよく知っている場合はスキップしても良いと思います。
2\.には研究にいかせるように自分の意見、ideaをかく項目を追加しました。

## 結果

### どんな論文？

BERTを文脈埋め込みとしてNMTに利用し、教師あり、半教師あり、教師なしのMTを行いこの手法の有効性を検証した

### 先行研究と比べてどこが凄い？

BERTは下流の言語理解タスクでは、文脈埋め込みではなく、fine-tuningとしてより一般的に利用されているが、NMTにおいてfine-tuneingよりも文脈埋め込みとして利用する方が優れており、その方向に沿って研究を考えるMotivationを示したこと。

### 技術や手法のポイントは？

BERTモデルをゼロから訓練することは多くの研究者にとって手が出ないことを考慮し、事前に訓練されたBERTモデルをNMTに活用することに焦点を当てている。

### どうやって有効だと検証した？

IWSLT, WMTデータセットを用いて合計14のタスクを行い、7つの最先端の結果を樹立した。

### 議論はある？

推論時間が45%増加するため、今後どう短縮していくか研究をする必要がある。また、このモデルをどう軽量化するかも課題。

### 次に読むべき論文は？

論文の最後で紹介されていた、知識蒸留を活用して、事前に訓練されたモデルをNMTと組み合わせる現代の研究2つ

[Distilling the Knowledge of BERT for Text Generation](https://openreview.net/forum?id=Bkgz_krKPB), Yen-Chun Chen et al., 2019

[Towards Making the Most of BERT in Neural Machine Translation](https://arxiv.org/abs/1908.05672), Jiacheng Yang et al., 2019

### 自分の意見、ideaは？

BERTの文脈埋め込みと同様なメカニズムで様々なオントロジーを利用する

BERT以外のものは使えるかを検討する。

## 感想
論文を読むときにフォーマットを意識して読めたので、最後にまとめやすかったです。慣れてくればもっと早く読めるになるはず！！！まだ論文をあまり読んだことがない人は最初から読んでみて比べてみると良いかもしれません。
【Unity】PUN2を学習する　ゲームを作る-2

この記事は、[【完走したい】楽しくいろいろやる Advent Calendar 2023](https://qiita.com/advent-calendar/2023/notbeginner)の8日目です。
# オブジェクト破壊
```
 public void GameFin()
    {
        if (photonView.IsMine)
        {
            Player owner = (Player)photonView.Owner;
            PhotonNetwork.Destroy(this.gameObject);
        }

    }
```
オーナー（管理者）の権限を渡す。
⇒オブジェクトを破壊できます。
ただし、通常のDestroyを使うとエラーが出ます。
#　勝ち負けがわかるようにする
エアホッケーなので相手のほうに入れたら本来は点が加算されますが、今回はサドンデス戦とします。
パックが奥に飛んで行ったら勝敗が出るようにします。
↓コード
```
  public void OnCollisionEnter(Collision collision)
    {

        if (collision.gameObject.name == "JudA")
        {
            GameObject GamePlayer = GameObject.Find("Cube(Clone)");
            id = GamePlayer.GetComponent<TFControll>().A;
            if (id == 1)
            {
                Debug.Log("1");
            }
            if (id == 2)
            {
                Debug.Log("2");
            }
            if (id == 1)
            {
                Lose.SetActive(true);

            }
            if (id == 2)
            {
                Win.SetActive(true);
            }

            if (photonView.IsMine)
            {
                Invoke("GameFin", 1f);
            }
        }
        if (collision.gameObject.name == "JudB")
        {
            Cube = GameObject.Find("Cube(Clone)");
            id = Cube.GetComponent<TFControll>().A;
            if (id == 1)
            {
                Debug.Log("1");
            }
            if (id == 2)
            {
                Debug.Log("2");
            }
            if (id == 1)
            {
                Win.SetActive(true);


            }
            if (id == 2)
            {
                Lose.SetActive(true);
            }

            if (photonView.IsMine)
            {
                Invoke("GameFin", 1f);
            }
        }





    }
```
２日かかりました。
Debug.Logが書いてあるところは動くか確認するた目のものなので消してOKです。
ざっくり説明すると
Cubeを見つけてAを取ってきて、idに代入
idの値に応じて勝ち負けを出します。
実は、このAの中身はプレイヤーの番号です。
詳しくは次の記事に書きます。

参考

https://zenn.dev/ekito_station/articles/destroy-network-object

https://zenn.dev/o8que/books/bdcb9af27bdd7d/viewer/e3765a

https://qiita.com/shoya-ishiguro/items/80b8cb53a4497d0c9b30

https://doc-api.photonengine.com/ja-jp/pun/current/class_photon_view.html

https://doc.photonengine.com/ja-jp/pun/current/lobby-and-matchmaking/userids-and-friends

https://teratail.com/questions/305148

https://tech.motoki-watanabe.net/entry/2019/01/31/071212

https://zenn.dev/o8que/books/bdcb9af27bdd7d/viewer/3305df

https://www.sejuku.net/blog/53526
OpenVPN CA入れ替え (EasyRSA 2.0)


# ことの始まり

2015年に設定して、運用を開始したマイOpenVPNですが、最近、急にiPhone, iPadからアクセスすると、次のエラーがでるようになった。つながらないと、色々面倒なので、なおすことにした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213097/7defb209-9f95-48c6-c197-877c05ca172e.png)

CAのhash algorithmが古いと言われてもなぁ、という感じ。


# いまの内容を調べてみる

いまのCAの内容がどうなっているか、調べてみる

```
# openssl x509 -text -noout -in ca.crt
```

Signature Algorithmに"sha1WithRSAEncryption"と出てきて、どうやらSHA1を利用しているみたい。

```
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            xx:xx:xx:xx:xx:xx:xx:xx
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C = XX, ST = XX, L = XX, O = XX, OU = XX, CN = XX, name = XX, emailAddress = XX
        Validity
            Not Before: Oct  4 XX:XX:XX 2015 GMT
            Not After : Oct  1 XX:XX:XX 2025 GMT
(snip)
```

これをSHA256とかSHA512に変えればいいのかな？


# どうやって変える？

3.0のケースは、ぐぐると色々出てきました。

```
set_var EASYRSA_DIGEST "sha512"
```

easyRSA 2.0において、この書式で設定される項目は、なかったので、他の方法を考えることが必要。
build-ca といった、build-xxx から呼ばれているpkitoolを見ていみると引数に、sha1があったので、そこをsha512へ書き換えてみる

```
easy-rsa/2.0 $ diff pkitool.org pkitool
325c325
< 	$OPENSSL req $BATCH -days $CA_EXPIRE $NODES_REQ -new -newkey rsa:$KEY_SIZE -sha1 \
---
> 	$OPENSSL req $BATCH -days $CA_EXPIRE $NODES_REQ -new -newkey rsa:$KEY_SIZE -sha512 \
359c359
< 	        -in "$FN.csr" $CA_EXT -md sha1 -config "$KEY_CONFIG" ) && \
---
> 	        -in "$FN.csr" $CA_EXT -md sha512 -config "$KEY_CONFIG" ) && \
```


# 変えてみた

変えたあと、build-caが動くか確認

```
easy-rsa/2.0# ./build-ca
Generating a RSA private key
.............+++++
.............................+++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [xx]:
State or Province Name (full name) [xx]:
Locality Name (eg, city) [xx]:
Organization Name (eg, company) [xx]:
Organizational Unit Name (eg, section) [xx]:
Common Name (eg, your name or your server's hostname) [xx]:
Name [xx]:
Email Address [xx]:
```

無事に完走して、ca.crt, ca.keyができてました。 中身を確認します。

```
# openssl x509 -text -noout -in ca.crt 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
        Signature Algorithm: sha512WithRSAEncryption
        Issuer: C = xx, ST = xx, L = xx, O = xx, OU = xx, CN = xx CA, name = xx, emailAddress = xx
        Validity
            Not Before: Dec xx xx:xx:xx 2023 GMT
            Not After : Mar xx xx:xx:xx 2050 GMT
```

Signature Algorithが、sha512WithRSAEncryptionと変わっていることが確認できた。これで、目的達成。


# 結果

新しいCAに合わせて、デバイス用のovpnファイルを修正。その後アップロードしたところ、無事に接続。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213097/23b29e9e-8704-9ff1-da48-c3db0fb1a227.png)


よしよし
Compose Material3に3つあるNavigationDrawerの違い

Compose Material3 には NavigationDrawer の実装が 3 つ存在しています。  
自分でもどれがどのような見た目でいつ使うのかわからなくなるので、スクショ付きで残しておきます。  


## 見た目の違いまとめ

|ModalNavigationDrawer|DismissibleNavigationDrawer|PermanentNavigationDrawer|
|:--:|:--:|:--:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/01d103e8-c0d9-d611-7edc-f6221c91e444.gif" width="300px"/>| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/ba130f0c-5873-6a2c-7988-0640de0a4809.gif" width="300px"/>| ![Screenshot_20231209_114325.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/92fef099-7a27-14db-de08-cc13d51638fa.png)|




## ModalNavigationDrawer
コンテンツの上に被さり Scrim が表示される NavigationDrawer です。  
Material3 より前からあった、NavigationDrawer といえばこれを思い浮かべることでしょう。  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/01d103e8-c0d9-d611-7edc-f6221c91e444.gif" width="300px"/>

https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#ModalNavigationDrawer(kotlin.Function0,androidx.compose.ui.Modifier,androidx.compose.material3.DrawerState,kotlin.Boolean,androidx.compose.ui.graphics.Color,kotlin.Function0)


## DismissibleNavigationDrawer
横からスライドして出てくる NavigationDrawer です。
この NavigationDrawer の使い道はコード内コメントで以下のように解説されています。

>Dismissible standard drawers can be used for layouts that prioritize content (such as a photo gallery) or for apps where users are unlikely to switch destinations often. They should use a visible navigation menu icon to open and close the drawer.


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/ba130f0c-5873-6a2c-7988-0640de0a4809.gif" width="300px"/>


https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#DismissibleNavigationDrawer(kotlin.Function0,androidx.compose.ui.Modifier,androidx.compose.material3.DrawerState,kotlin.Boolean,kotlin.Function0)

## PermanentNavigationDrawer
常に表示する NavigationDrawer です。
モバイルでは ModalNavigationDrawer を表示し、タブレットやデスクトップなどの大画面で PermanentNavigationDrawer に切り替えて表示するといった感じで組み合わせて使用します。  

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/9b1bb59b-597c-475f-5a9a-dd417fba3255.png" width="500px" />


https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#PermanentNavigationDrawer(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Function0)
【Unity】PUN2を学習する　ゲームを作る-1

この記事は、[【完走したい】楽しくいろいろやる Advent Calendar 2023](https://qiita.com/advent-calendar/2023/notbeginner)の7日目です。
エアホッケーを作ります。
続きです。３日目です。
終わらないので明日もやります。
# ホッケーのパックを作る
はじくやつです。
プッシャーと同様、オブジェクトを作ってprefab化します。
二人そろってゲームを始めるときに出るようにします。
<b>重要　２つ目のオブジェクトを作成するときはInstantiateで生成するとエラーが出ます</b>
どうやら、prefab化したオブジェクトをいったんHierarchyに戻し、Photon ViewとPhoton Transform Viewをつけるだけでいいみたいです。
![スクリーンショット (154).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/c2a8434c-896e-06bd-feec-b087781e2451.png)
こんな感じになりました。
# その後
いろいろあって3dのプロジェクトに変更しました。
どうやったのかというと、
Edit>projectsettings>Editor
の中の
'Defalt Behaviour Mode'を3dにしただけです。
簡単に変更できます。
# 土台を作る
全て作った後に撮った写真なのでわかりにくいかと思いますが、今は
・地面
・壁
があれば十分です
↓画像
![スクリーンショット 2023-12-09 124311.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/4f4f8e88-6b08-39ec-7d21-684579eea4f0.png)
青い壁がちょっと変な形をしているのがわかると思います。
実は、ボールのはね方によってボールが壁にくっついてしまうことがありました。
その為、壁にくっついたボールを取るために出っ張りを付けました。
このでっぱりは、scale(1,1,1)のcubeをx軸に45度回転させることで作れます。
# パック（作り直し）
sphereで代用しました
中身
```
using Photon.Pun;
using Photon.Realtime;
using Unity.VisualScripting;
using static Unity.VisualScripting.Member;

public class BallControll : MonoBehaviourPunCallbacks
{private Rigidbody rb;
    public bool Once = false;
    public int BallRotate;
    // Start is called before the first frame update
    void Start()
    {
    
     

    }

    // Update is called once per frame
    void Update()
    {
        if (PhotonNetwork.InRoom)
        {
           
            if (PhotonNetwork.CurrentRoom.PlayerCount >= 2)
            {
                if (photonView.OwnerActorNr == 0)
                {
                    if (Once == false)
                    {
                        Once = true;
                        rb = this.GetComponent<Rigidbody>();
                        BallRotate = Random.Range(0, 360);
                        Transform myTransform = this.transform;
                        Vector3 localAngle = myTransform.localEulerAngles;
                        localAngle.y = BallRotate;
                        myTransform.localEulerAngles = localAngle;
                        Vector3 Kasoku = new Vector3(4f, 0, 4f);
                        rb.AddForce(Kasoku, ForceMode.VelocityChange);

                    }

                }
            }
        }
    }
    
}

```
ボールをランダムに角度をつけて、速度をつけています。
が、これではなぜか角度は変えられませんでした。
ボールは動いているので、とりあえずOKです。
今日の分ここまで
# まとめ
現在のルーム人数カウント
'PhotonNetwork.CurrentRoom.PlayerCount'
などを学びました。
参考

https://www.youtube.com/watch?v=A9PuR8BHs6U

https://www.sejuku.net/blog/54896

https://cgbox.jp/2023/09/18/unity-friction/

https://3dunity.org/game-create-lesson/action-pazzle-game/tag-collision-judgement/
GitHub Actionsでcustomize-uploaderを実行してアプリにカスタマイズファイルを自動適用しよう

## はじめに
kintoneカスタマイズのテストには専らVSCodeの[LiveServer](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer)を使っているわけですが、ローカルサーバーなので自分自身しか動作確認ができないという問題点があります。
そこで出てくるのが[customize-uploader](https://cybozu.dev/ja/kintone/sdk/development-environment/customize-uploader/)なのですが、結局ファイルを同期する必要があり、チームでカスタマイズを進める場合はGitHubを併用せざるを得ない状況になります。

今回は、GitHubのMainブランチにマージされたときにGitHub Actionsを実行し、customize-uploaderでkintoneにカスタマイズファイルを自動適用させる仕組みづくりをやっていこうと思います。

## 処理の流れ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535789/7d326d1f-8288-9cf5-60bb-d53013eb0429.png)

## VSCode
今回は`src/script.js`と`src/style.css`をアップロードする形にします。
GitHub Actionsがメインの記事なのでGitHubへのPush操作などは割愛します。

### ディレクトリ構成
```
.
├── src
│   ├── script.js
│   └── style.css
└── dest
    └── customize-manifest.json
```

#### customize-manifest.json
```json
{
  "app": "適用するアプリID",
  "scope": "ALL",
  "desktop": {
    "js": ["src/script.js"],
    "css": ["src/style.css"]
  },
  "mobile": {
    "js": [],
    "css": []
  }
}
```

## GitHub Actions
GitHub Actionsでは`main`ブランチにpushされた場合にcustomize-uploaderを実行するymlファイルを作成します。

### secretsの設定
公開リポジトリの場合は、kintoneのURLやユーザー名・パスワードなど秘匿したい情報があります。
GitHub Actionsでは環境変数が用意されていますので、必ずそちらに保存しましょう。

リポジトリの上部メニューから下記の設定に遷移します。
`Settings > Secrets & Variables > Actions`
その中の`Repository secrets`の`New repository secrets`を押して各項目を登録します。

今回は下記の３項目を設定できればOKです。
※変数名を変える場合は後述するymlファイルの変数名も必ず変更してください。

![スクリーンショット 2023-12-09 12.26.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535789/b85a53e5-59c8-5fde-c919-844ec7fd0982.png)

チームで活用する場合はアプリ管理権限のあるユーザーアカウントをシステム用で一つ用意して使うと良いかもしれませんね。


### Workflowの作成
それではいよいよWorkflowの作成です。
リポジトリの上部メニューから`Actions > New workflow > set up a workflow yourself`をクリックします。
ymlファイルを作成するエディターが表示されますので、下記のコードを適用し`Commit changes`を行ってください。
※事前にGitHubの`main`ブランチにカスタマイズファイルをpushしておくことを忘れないようにしてください

```yml
name: Deploy to Kintone
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: 14

      - name: Install @kintone/customize-uploader
        run: npm install -g @kintone/customize-uploader
      
      - name: Deploy to Kintone
        run: |
          kintone-customize-uploader --base-url ${{ secrets.KINTONE_DOMAIN }} --username ${{ secrets.KINTONE_USER_NAME }} --password ${{ secrets.KINTONE_USER_PASSWORD }} dest/customize-manifest.json
```

### 動作しない時
- 環境変数に登録している値が正しいかを確認しましょう（KINTONE_DOMAINは`https://example.cybozu.com`の形式です）
- [ディレクトリ構成](###ディレクトリ構成)が正しいかを確認しましょう
- 環境変数で設定したkintoneアカウントが該当アプリの管理権限をもっているかを確認しましょう
【Go言語】構造体

## 構造体とは
**構造体**は、異なる型のデータを一つの単位としてまとめるための複合型のこと。
構造体は非常に重要な役割を担い、データ構造を定義するのに広く用いられる。

### 構造体の定義
構造体の定義は、`type`キーワードに続いて`構造体の名前`と`struct`キーワードを用いて行う。
ブレース`{}`内には、構造体のフィールドを列挙する。

#### サンプル
```go
type Book struct {
    Title      string
    Author     string
    Publisher  string
    ReleasedAt time.Time
    ISBN       string
}
```

### 構造体のインスタンス化
構造体自体は単なる型であり、メモリ上に実体を持つインスタンスを生成する必要がある。

#### サンプル
```go
package main

import (
	"fmt"
	"time"
)

type Book struct {
	Title      string
	Author     string
	Publisher  string
	ReleasedAt time.Time
	ISBN       string
}

func main() {
	var b1 Book                   // 全フィールドをゼロ値で初期化
	b2 := Book{Title: "初めてのGo言語"} // 初期値を指定
	b3 := &Book{Title: "実用 Go言語"} // ポインターとしてインスタンスを生成

	fmt.Println(b1) // {   0001-01-01 00:00:00 +0000 UTC }
	fmt.Println(b2) // {初めてのGo言語   0001-01-01 00:00:00 +0000 UTC }
	fmt.Println(b3) // &{実用 Go言語   0001-01-01 00:00:00 +0000 UTC }

}

```

### JSONとの相互変換
JSONファイルを読み込み、それを構造体にマッピングすることができる。

#### サンプル
`main.go`と同じディレクトリに`book.json`を用意する

```json
{
    "title": "架空のプログラミング入門",
    "author": "山田太郎",
    "publisher": "テスト出版社",
    "release_at": "2022-04-01T00:00:00Z",
    "isbn": "123-4567890123"
}
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"
)

// Book 構造体はJSONとの相互変換を可能にするタグ付きフィールドを持つ
type Book struct {
	Title      string    `json:"title"`
	Author     string    `json:"author"`
	Publisher  string    `json:"publisher"`
	ReleasedAt time.Time `json:"release_at"`
	ISBN       string    `json:"isbn"`
}

func main() {
	f, err := os.Open("book.json")
	if err != nil {
		log.Fatal("file open error: ", err)
	}
	defer f.Close()

	d := json.NewDecoder(f)
	var b Book
	err = d.Decode(&b)
	if err != nil {
		log.Fatal("decode error: ", err)
	}

	fmt.Println(b) // {架空のプログラミング入門 山田太郎 テスト出版社 2022-04-01 00:00:00 +0000 UTC 123-4567890123}
}

```

## 参考
https://www.oreilly.co.jp/books/9784873119694/
Dockerを使ってPrismを指定のポートで立ち上げる

Prismを指定のポートで立ち上げようと思った時、スムーズにいかなかったので記事にする。

# どうハマったか
Prismを4011番Portでリスンさせたい。

```
$ docker run --init --rm \
-v $(pwd)/examples/v3.0/api-with-examples.json:/api-with-examples.json \
-p 4011:4011 \
stoplight/prism:4 mock -h 0.0.0.0 "/api-with-examples.json" 
```
を実行すると、
```
[3:18:38 AM] › [CLI] ✔  success   Prism is listening on http://0.0.0.0:4010
```
あれ、、4010でPrismがリスンしている状態になる。

# 原因
図で説明すると、以下のようになっている。
```
[ホスト]             [Docker コンテナ]
  |                      |
  |  :4011               |  :4011
  |----->|               |----->| Prism
  |                      |      :4010 (内部ポート)
  |                      |

```
Prismのポートの指定ができておらず、デフォルトの4010で立ち上がっていた。

# 解決策

```
$ docker run --init --rm \
-v $(pwd)/examples/v3.0/api-with-examples.json:/api-with-examples.json \
-p 4011:4011 \
stoplight/prism:4 mock -h 0.0.0.0 -p 4011 "/api-with-examples.json" 
```
を実行すると、
```
[3:29:00 AM] › [CLI] ✔  success   Prism is listening on http://0.0.0.0:4011
```
はい、Prismが4011ポートでリスンしている状態になりました。
symfonyでvalidationのメッセージを日本語化したメモ


https://symfony.com/doc/current/validation/translations.html

基本は ↑ こちらに沿って進めればOK

https://github.com/symfony/validator/tree/7.0/Resources/translations

symfony/translation で配置されるファイルは ↑ こちら

https://symfony.com/doc/current/translation.html#translation-resource-file-names-and-locations

↑ こちらにあるとおり、 validators.ja.xlf を translations/ ディレクトリにコピーします

ただ、各リンクのとおりに進めても、invalidのメッセージは英語のままでした

ファイル名の形式が `translation_domain.言語.xlf` となっているみたいで、
validator.yaml の translation_domain と合わせる必要があります

```diff
# config/packages/validator.yaml
framework:
    validation:
-        translation_domain: validation_errors
+        translation_domain: validators
```

これで日本語になりました

ごきげんよう
【Unity初歩】~敵を増殖させる~

# はじめに
前回ステージを作成し、🦀の動きに合わせてカメラが追従するようにしました。
今回はゲームオーバー要員となる敵を一定時間経過ごとに増やしていきます。

前回の記事

https://qiita.com/usomaru/items/1971b55893ad96d6d6bb

# やったこと
敵を増やすスクリプト作成を試すために、一定時間が経過するとランダムな場所から敵(🦐)が降ってくるようにしました。

# 🦐に対するスクリプトを変更する
現在エビには左横移動するスクリプトが当たっているため、空から降ってくるスクリプトに変更しました。

```C#
transform.Translate(0, -0.1f, 0);

if (transform.position.y < -5)
{
    Destroy(gameObject);
}
```


# 敵を時間経過で増やす
前回ステージを作成した時と同じ要領でPrefabを作成します。
原本をプロジェクトウィンドウへ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/f8063994-f160-97fe-6f0c-7d1324168af9.png)

作成したPrefabの名前は「ebiPrefab」に。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/25c8a4fc-75f6-3256-b7e1-6de774ca5bc4.png)

今回はステージを作成した時とは違い、一定時間経過でPrefabを増やさないといけません。
そのため、シーンビューに追加するのではなく、スクリプトをかきます。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyGenerator : MonoBehaviour
{
    public GameObject ebiPrefab;
    float span = 2.0f;
    float delta = 0;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        this.delta += Time.deltaTime;
        if (this.delta > this.span)
        {
            this.delta = 0;
            GameObject go = Instantiate(ebiPrefab) as GameObject;
            Debug.Log(go);
            int px = Random.Range(0, 20);
            go.transform.position = new Vector3(px, 5, 0);
        }
    }
}
```
2秒間隔で🦐を生成しています。


スクリプトがかけたら、空のオブジェクトを作成し、そこにスクリプトをアタッチします。
このオブジェクトに敵生成スクリプトをアタッチすることによって、このオブジェクトは敵生成工場オブジェクトとして機能することになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/76a4d73c-1763-a7ec-93da-87560158275d.png)

オブジェクト名はEbiGenerator
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/993b0422-7325-fa73-0112-afa70105aaf0.png)

動かしてみると、エラーがでて動かなくなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/00a258dd-55c1-9cde-69fa-d725525942ea.png)

オブジェクトの実態がないため発生したようです。
ここでオブジェクトを差し込む必要がありました。
ここには先ほどのスクリプトでpublic宣言をした変数が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/84184657-b752-03cf-b2b7-f53d5ef7ecfd.png)

変数へプロジェクトウィンドウの🦐Prefabをドラッグアンドドロップで移動させて差し込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/a68c035b-73af-4131-fcff-b8b70007f4fe.png)

エラーを解消して動かしてみると、一定時間でエビが空から降ってくるようになりました。

https://twitter.com/usomaru26/status/1733326874355585527

# おわりに
一定時間経過でランダムな場所に敵を増殖させることができ、どんどんゲームっぽくなりました。
(🦐が空から降ってきてカオスですが)
389 Directory Server構築時のldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

# 事象
389 Directory Server構築にldapsearchでldapsを使用すると以下のエラーが出ました。

```
# ldapsearch -LLL -x -H ldaps://127.0.0.1/ -b dc=sample,dc=com
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

```

# 解決方法
以下のサイトが参考になりました。
https://www.conversion.co.jp/tecblog/20200303/

```
vi /etc/openldap/ldap.conf

#
# LDAP Defaults
#

# See ldap.conf(5) for details
# This file should be world readable but not world writable.

#BASE   dc=example,dc=com
#URI    ldap://ldap.example.com ldap://ldap-master.example.com:666

#SIZELIMIT      12
#TIMELIMIT      15
#DEREF          never

# When no CA certificates are specified the Shared System Certificates
# are in use. In order to have these available along with the ones specified
# by TLS_CACERTDIR one has to include them explicitly:
#TLS_CACERT     /etc/pki/tls/cert.pem

# System-wide Crypto Policies provide up to date cipher suite which should
# be used unless one needs a finer grinded selection of ciphers. Hence, the
# PROFILE=SYSTEM value represents the default behavior which is in place
# when no explicit setting is used. (see openssl-ciphers(1) for more info)
#TLS_CIPHER_SUITE PROFILE=SYSTEM

# Turning this off breaks GSSAPI used with krb5 when rdns = false
SASL_NOCANON    on
TLS_REQCERT never  ←左記の設定を追加　今回はneverに設定しました。
環境によって異なるため、上記の設定は確認してください。

```
389 Directory Serverのサービス名は設定した値にしてください
```
systemctl restart dirsrv@389 Directory Serverインスタンスの名前.service
```
# 解決しました
```
[root@ip-10-0-9-116 ~]# ldapsearch -LLL -x -H ldaps://127.0.0.1/ -b dc=sample,dc=com
dn: dc=sample,dc=com
objectClass: top
objectClass: domain
dc: sample
description: dc=sample,dc=com
```
PythonのデコレータはSpringでいうAOPと同じ概念

Pythonのデコレータってめちゃくちゃ難しいなーって思ってたけど、結局表題に帰結する。
「引数で関数を受け取って、関数を返す」とか難しいことを言っている記事が多かったけど、結局、その対象のメソッドを実行する前後に何をしたいかどうかだけ。


```decorator.py
def foo(func: function):
    def wrapper(*args, **kwargs):
        print("事前に実行します。")
        value = func(*args, **kwargs)
        print("事後に実行します。")
        return value

    return wrapper
```

```main.py
from decorator import foo

@foo
def bar():
    print("barです。")

bar()
```

結果は、下記になる。
```txt
事前に実行します。
barです。
事後に実行します。
```

結局、barが実行される前に、fooのwrapperの関数が呼ばれるだけだ。
wrapperの引数は、barの引数依存をなくすためにあるだけ。

foo -> wrapper -> print("事前に実行します。") 
-> func -> print("barです。")
-> wrapper -> print("事後に実行します。")
なんとなくIllustratorをいじってみた。初心者の試行錯誤。

### まず初めに

初めまして。4月に入学し、もう半年以上が経っていることにやっと自覚を持ち始めたN高生の鮫と申します。Twitterと音楽、相方が生き甲斐の人です。宜しくお願いします。

アドベントカレンダーに関しては初なため、変なことや、逸れていたりしたら、本当にごめんなさい。
#

#### 目次

1　なぜIllustratorに関してなのか
2 自分の比較。作品の比較と学び。
3 比較から学んだ、基礎応用。
4 さいごに

#

##### なぜIllustratorに関してなのか

自分が元々興味を持っていることに関して、『デザイン』についてですが、自分は元々グラフィックデザインに興味を持っており、N高に入る前からIllustratorをいじっておりました。高校に入り始めてから、Illustratorにどっぷり浸かり、今沼から抜け出せなくなっております。

そんな人間のIllustratorをいじってきた記録はこちら。

### 初期の頃と今の制作物を比較する。


![ロストボーイ　ステッカー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626048/d694c64e-0a5e-6aa2-8442-e16537971e0b.png)

>上記はamazarashi 七号線ロストボーイズより、「ロストボーイ」の創作ステッカー

こちらが初期、初めてステッカー作りと言う点からIllustratorを使用したものになります。
自分の好きなバンドのアルバムから、二次創作...?と言う形で作成いたしました。

ほぼ全て図形であり、文字のロゴの線もアルバムと同じように一つ一つ作っております。

初期はかなりものや表現のためのフィルターなどは使っていませんでした。
そして空白がありますが、あまり意味のこもった感じではなく、"amazarashi"という部分もやっと入れた感があります。


### 今のもの

![永遠市.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626048/17b21c59-76ab-610a-704d-03e4e1b140d0.png)

>上記はamazarashi　の「永遠市」をイメージしながら作ったもの。

かなり図形の利便さ（ただ配置するだけではない）と言うことが分かり始めた頃ですね。
何個か図形を重ねて、fx.（エフェクト）でぼかしなどを入れています。
なにかとfx.をいじったりすると創作の幅が広がっていくものですね。

ですが、まだ文字などの感じ（雰囲気）が合っている感じはあまりしませんね。
ですがfx.を乱用していくのはまだまだだったみたいです。この時は。


### 改良を重ねた結果....


![永遠市　ヘッダー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626048/4d84ac20-c450-04ba-40b0-0f05cd881935.png)

>上記に関してもamazarashi　の「永遠市」をイメージしながら作ったもの

かなり「永遠市」の部分を元の文字を変形し、作っております。fx.の入れ方にも慣れてきました。
その時は少し近未来感を出すために、左右のマーブル模様を二重にし、ぼかしを若干fx.から入れ、レーザー感を出しています。

自分としてはかなりいい感じに仕上がりました。



### Illustratorの基礎と応用

基礎的には図形や文字を並べるから始めるIllustrator生活でしたが、
応用ではfx.や変形、パス〜が関係してくることが分かります。

Illustratorはただ変形させるだけではなく、Photoshopでの効果もあることがわかると、相当世界が広がるかともいます。あとfx.関連に関してもですね。

fx.の詳細↓

![スクリーンショット 2023-12-08 21.35.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626048/6e8080de-c048-98fa-5461-b76a8f815c78.png)

色々な効果を組み合わせていくことも一つのデザインにつながるかもしれませんね。


#### さいごに

なかなかの駄文っぷりでしたが、軽く自分の状態を整理する上で、そしてイラレを細かく使用してきた半年で、なにがあったかを軽くお話ししたものでした。

いかがだったでしょうか？
Illustrator、いじってみませんか？

私は自分の好きなバンドのものをまず創作して、これからは一次創作的なことに取り組んでまいりたいと思います。長文にお付き合いいただきありがとうございました...!!!!!!!!
データチャートをブラウザで表示する方法（Chart.js）

## ブラウザでチャートを表示する方法
![スクリーンショット 2023-12-09 12.08.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/a04c257f-2865-862e-46ee-52e1b0a66769.png)

Chart.jsとは、Webページにチャートを
描画するための軽量かつ強力な
JavaScriptライブラリです。

HTML5の<canvas>要素を使用して
・折れ線グラフ
・棒グラフ
・円グラフ
など、さまざまなタイプのチャートを
作成することができます。

また、レスポンシブデザインに対応しており
さまざまなデバイスで美しいチャートを
表示できるのが特徴です。

#### ＜チャートの作成例＞
以下に、Chart.jsを使用して
棒グラフを作成する簡単な例を示します。

この例では、さまざまな色に対する
得票数を表すチャートを作成しています。
https://codepen.io/Toma-0205/pen/bGzzXRj
※codepenでコードとブラウザ表示を
&nbsp; &nbsp; 同時に確認することができます。
![スクリーンショット 2023-12-09 12.18.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/570f5210-10ee-2483-fc85-cc425be07022.png)


実際のコード↓
```
<!DOCTYPE html>
<html lang="ja">
<head>
    <!-- 必要なメタタグとBootstrapのCSSをリンク -->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>BootstrapとChart.jsの例</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
    <div class="container">
        <h2 class="text-center mt-4">チャートの例</h2>
        <div class="row">
            <div class="col-md-6">
                <!-- チャートを表示するためのcanvas要素 -->
                <canvas id="myChart" width="400" height="400"></canvas>
            </div>
        </div>
    </div>

    <script>
        // チャートの設定
        var ctx = document.getElementById('myChart').getContext('2d');
        var myChart = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: ['赤', '青', '黄', '緑', '紫', 'オレンジ'],
                datasets: [{
                    label: '色ごとの得票数',
                    data: [12, 19, 3, 5, 2, 3],
                    backgroundColor: [
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(54, 162, 235, 0.2)',
                        'rgba(255, 206, 86, 0.2)',
                        'rgba(75, 192, 192, 0.2)',
                        'rgba(153, 102, 255, 0.2)',
                        'rgba(255, 159, 64, 0.2)'
                    ],
                    borderColor: [
                        'rgba(255, 99, 132, 1)',
                        'rgba(54, 162, 235, 1)',
                        'rgba(255, 206, 86, 1)',
                        'rgba(75, 192, 192, 1)',
                        'rgba(153, 102, 255, 1)',
                        'rgba(255, 159, 64, 1)'
                    ],
                    borderWidth: 1
                }]
            },
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true
                        }
                    }]
                }
            }
        });
    </script>
</body>
</html>
```

## まとめ
Chart.jsを使用することで
ブラウザ上に美しいチャートを
簡単に表示することができます。

これにより、ユーザーに対してより
理解しやすいデータの視覚化を
提供することが可能になります。
Azure AI Searchでのデータインポートとベクター化の実践ガイド

本記事は [OpenAI活用法 Advent Calendar 2023 by ナレコム](https://qiita.com/advent-calendar/2023/openai-knowledgecommunication) の8日目の記事です。

OpenAI活用法 Advent Calendar 2023 by ナレコム ではGPTsを含めた最新のOpenAIの活用法について紹介します。

### はじめに

前回の記事で、Azure OpenAIのEmbeddingモデルの作成とAzure AI Services Multi-Service Accountの設定について学びました。これらは、Azure AI Searchの強力な「データをベクター化する」機能を活用するための基盤となります。今回の記事では、このプロセスの次のステップ、つまり「データのインポートとベクター化」に焦点を当てます。

本セクションでは、実際のデータをAzure AI Searchにインポートする方法と、そのデータを効果的にベクター化する手順を、ステップ・バイ・ステップで解説します。このプロセスを通じて、データがどのように機械が理解できる形式に変換され、Azure AI Searchの検索機能やデータ分析能力がどのように向上するかを見ていきます。

インポートからベクター化までのプロセスは、データをより深く掘り下げ、その潜在的な価値を最大限に引き出すために重要です。この記事が、Azure AI Searchを使用してデータをより効果的に活用するための実践的なガイドとなることを目指しています。

### Azure AI Searchの作成

1. Azureポータルにアクセスします。
1. 上部検索ウィンドウから「AI Search」と入力し、「AI Search」を選択します。
1. 「AI Search」ページに移動し、「＋作成」をクリックします。
1. 「検索サービスを作成する」ページでは、サブスクリプション・リソースグループ、場所を選択し、任意のサービス名を入力します。
1. 価格レベルは最初は標準（Standard）が選ばれていますので適切なものを選びます。検証で利用するのであればサブスクリプションあたり1つ **Free** を作ることも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/709b75fc-cec7-8a0d-917e-ede134ff0441.png)
1. 「確認および作成」まで進めて、作成します。

### データインポートとベクター化の実施

事前準備としてベクター化したいデータ（PDFやCSVなど。フォルダ指定で複数ファイルも可）をBlobにアップロードしておきます。

1. 作成した「Azure AI Search」に移動します。
1. ページ上部にある「データのインポートとベクター化」をクリックします。
1. 事前準備でアップロードしたBlobフォルダーもしくはファイルを指定して「次へ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/8f1d2440-c6df-844e-b4c6-260c20154411.png)
1. 次のステップでは前記事で作成したEmbedding（埋め込み）モデルとAzure AI Services Multi-Service Accountを選択し「次へ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/f1d25460-b9cc-59a8-14f7-5dc6de3a6287.png)
1. 確認画面で問題なければ「作成」をクリックします。以下の画面が表示されるので「検索の開始」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/0c511dd5-2f18-7d37-f4c2-ea387289c4e6.png)
1. 少し時間が経過してから「最新の情報に更新」をクリックすると以下のように数字が表示されれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/e6f85ca9-85b1-5690-0acc-92bbc2f22c60.png)

### まとめ

本記事では、Azure AI Searchを利用して、データのインポートとベクター化のプロセスを詳細に説明しました。このプロセスは、データをAzure AI Searchに統合し、検索機能やデータ分析の能力を強化するための重要なステップです。

#### 主なポイント

1. **データのインポート**: Azure AI Searchへのデータインポートは、データをAzure環境に取り込む初歩的なステップです。これにより、データはAzure AI Searchの強力な検索エンジンと統合され、利用可能になります。

2. **データのベクター化**: データをベクター化することで、Azure OpenAIのEmbeddingモデルを使用してデータを機械が理解できる形式に変換します。これにより、データ分析の精度が向上し、より深い洞察が得られるようになります。

Azure AI Searchのデータインポートとベクター化プロセスは、データの価値を最大限に引き出すための重要なステップです。

---

また、ナレッジコミュニケーションでは  **「[Musubite](https://recruiting.musubite-job.com/features/company/knowledge-communication)」** というエンジニア同士のカジュアルトークサービスを利用しています！この記事にあるような生成AI 技術を使ったプロジェクトに携わるメンバーと直接話せるサービスですので興味がある方は是非利用を検討してください！

https://recruiting.musubite-job.com/features/company/knowledge-communication
Ruby – grepに使う正規表現をエスケープして埋め込む例 ( fill in escaped regexp to grep pattern )

# 例

カッコが正規表現として扱われしまい、ヒットしない


```rb
['(ABC)_XYZ'].grep(/(ABC)_XYZ/)
# => []
```

ヒットする

```rb
['(ABC)_XYZ'].grep(/#{Regexp.escape('(ABC)')}_XYZ/)
# => ["(ABC)_XYZ"]
```


# チャットメンバー募集


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

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


# Twitter

https://twitter.com/YumaInaura
IntelliJでAWS Lambdaの単体テストをローカル実行する

（自分用メモのため編集中です）
# 概要
AWS Lambda関数自体のテストはJUnit等で単体テストを書けば行えるが、LambdaからS3の特定のバケットに書き込みを行うなどのテストはAWSにデプロイしないとできないという悩みがあった。10MBくらいのコードを毎回アップロードしてテストしていたが、AWS CLIを使ったとしてもあまりにもめんどくさいし地球に優しくないので、ローカルでAWS環境をレプリケートしてテストできたらとても嬉しい。
この項目では、AWS環境をローカルにレプリケートして、各サービスとの連携をテストできるようにする方法を説明する。
Lambdaと接続をテストできるAWSサービスは以下の通り
・S3
・・・

# 仕組み
各AWSサービスのモックをDockerコンテナを使用してローカルマシン内に構築することで、テストを行える。ただ、ここで構築した内容を本番環境に持っていくのが難しそうという悩みもある。

# 必要なもの

### SAM CLI
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html

SAM（Serverless Apprication Model)
上記URLからSAM CLIをインストールする
### Localstack

https://qiita.com/rio_matsui/items/e0c2c772d4579d00a312

https://qiita.com/Shoma0210/items/258e8422d5341160624b

# 手順

### IntelliJから新規プロジェクトを起動
からAWS Serverless Appricationの
IntelliJの新規プロジェクト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636063/e81baf8d-a7cf-8ca6-3044-e26948dc5830.png)

→AWS Serverless Apprication
→SAM Templateが選択できていることを確認


### フロー的な詳細

https://qiita.com/kalzit/items/5d64f93bf75aaaad9915

※GradleはJDK17じゃないと動かないので、モジュールのJDKは17にする必要がある。
AWSコンテナ設計・構築［本格］入門

[AWSコンテナ設計・構築［本格］入門](https://www.amazon.co.jp/AWS%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E8%A8%AD%E8%A8%88%E3%83%BB%E6%A7%8B%E7%AF%89%EF%BC%BB%E6%9C%AC%E6%A0%BC%EF%BC%BD%E5%85%A5%E9%96%80-%E6%96%B0%E4%BA%95-%E9%9B%85%E4%B9%9F-ebook/dp/B09DKZC1ZH/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)を読みました。
備忘メモとして残しておきます。



## ロギング設計

### CloudWatch Logs と FireLens

- **CloudWatch Logs**
  - 例）サブスクリプションフィルター: 指定した文字列を含むログのみを抽出する。
    - 抽出したログを Lambda に連携して障害を通知させる。

- **FireLens**
  - AWS外のSaaSへのログ転送がしやすい。CloudWatch Logs にもログ転送が可能。

## メトリクス設計

メトリクスは、定量的な指標として定期的に計測/収集されるシステム内部動作のデータです。CloudWatch メトリクスと CloudWatch Container Insights に分けられます。

- **CloudWatch メトリクス**
  - CPU使用率、メモリ使用率 (1分間隔、ECSサービス単位)。
  - ECSタスクレベルで収集可能。ディスクやネットワーク情報も収集可能。

## Bastion設計

各サーバへのログインが必要な際に、セキュリティ面や運用コスト面を考慮した設計が重要です。

- セッションマネージャー経由の接続で、SSH接続が不要。
  - IAM権限でログイン可能であり、セキュリティ設定をIAMに集中管理できます。

## コンテナイメージの脆弱性スキャン

継続的かつ自動的に実施することが重要です。CI/CDに仕組みを取り入れます。

- CI/CDが実行されなければ脆弱性スキャンが実施されないため、定期的な手動スキャンが必要です。
  - CloudWatch Events から Lambda を実行できます。

## 平文の秘密情報対策

秘密情報を Secrets Manager や SSM パラメータストアに格納することで、環境変数として安全に提供できます。

- 各格納先のARNと環境変数名をタスク定義内でマッピングすることで、コンテナイメージ内のOS環境変数として認識させます。

## 信頼性設計

### マルチAZによる可用性向上

FargateでECSサービスを稼働させると、ECSサービス内部がベストエフォートでAZ間の負荷バランスを調整しながらタスク配置します。

### 障害時切り離しと復旧

- **CloudWatchを活用したECSタスクの障害検知**
  - RunningTaskCount と TaskCount メトリクスを組み合わせます。
- ECSサービスによるECSタスクの自動復旧
- ALBと連動したECSタスクの切り離しと自動復旧
- リタイアとリサイクルによるECSタスク停止への対処
  - リタイア：AWS内部のHW障害や脆弱性検知時、新しいECSタスクに置き換えるイベント
  - リサイクル：Fargate上で稼働しているECSタスクについて、パッチ適用や内部インフラストラクチャ更新のイベント

### システムメンテナンス時のサービス停止

メンテナンス時、SorryページやSorryコンテンツを返却できることが理想です。ALBのリスナールールの定義に設定できます。

## ECR

ECRはリージョンごとに存在するサービスです。VPC内管理サーバからECRへアクセスするには、インターネット向けOutbonding通信かVPCエンドポイントを使用する必要があります。
Spotify APIでのkeyとmodeを対応付けて出力してみた！

# はじめに
初めまして。Qiita初投稿で不慣れにつき、読みにくい箇所があるとは思いますが、よろしくお願いいたします！！

# Spotify APIについて
Spotify APIでは様々な値を取得することができます。
例えば、曲全体の印象を数値で表した`audio_features`ではその曲がどれくらいアコースティックなのかを表すacousticness、その曲がどれだけ踊れる楽曲なのかを表すdanceabilityといったようなものがあります。

詳しくはこちらの記事をご参照ください。めっちゃわかりやすくまとめてくださっています。
[PythonでSpotify API [audio_features編]](https://qiita.com/EkatoPgm/items/f88b6f002fd15defce71)

# なにをしたいのか
その中で、keyでは曲のキーを取得することができるのですが、これが0 = C, 1 = C♯/D♭, 2 = D...のように対応付けられています。また、modeではMajorが1で、minorが0に割り振られています。雰囲気的には、Majorが明るい感じで、minorが暗い感じの楽曲のことです。

これらが数値で表されているのがどうも直感的に理解することが難しいなーっていうことでこれらを対応させたコードを書いてみました。

# 実装
以前Spotify APIを触ってた時にPythonを使用していたため、今回もPythonで書くことに。

```python:python
def key_and_mode(key, mode):
    key_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
    mode_names = ['minor', 'Major']

    key_name = key_names[key]
    mode_name = mode_names[mode]

    return f"{key_name}{mode_name}"
```

これでkeyとmodeを対応付けることに成功しました。

たとえばkey = 4, mode = 0というふうに指定してみたときの出力結果はこちら。

```
Eminor
```

表示されてほしいように出力させることができました。

## 本当は。。。
本当はSpotify APIをごりごりいじって入力された曲に対して似ている曲を出力したかったのですが、リクエスト制限がかかってしまって期限内に記事の投稿ができなさそうだったので、諦めましたorz

Spotifyをもとに似ている曲を表示してくれるサイト[musicstax](https://musicstax.com/)を覗いた感じ、入力曲に対してtempo, roudness, danceabilityを重視しているようでした。

しかし、曲調を特徴づけるためにkeyとmodeは外せないでしょ！と思っているので(異論は認めます)、指定したプレイリストの範囲から条件に合った曲(=似ている曲)を表示できるようにさせたいなーと思っています。

# おわりに
今回は、やりたかったことの1割にも満たないくらいの準備段階の関数を作成してみました。

数値だけで直感的な理解がしづらいというところに少しストレスがあったため、今後は作成した関数をインポートすることで解消できそうです。

いずれちゃんと、納得のいく似ている曲の表示ができるようになっていたいなあ。。。


稚拙な文章だったかとは思いますが、**最後まで見てくださってありがとうございました！！**


最後に、参考にさせていただいた記事とmusicstaxのリンクをもう一度貼っておきます。

https://qiita.com/EkatoPgm/items/f88b6f002fd15defce71


https://musicstax.com/