OmniAICreator/Qiita-1.07M huggingface dataset:
Homomorphic Mapped Types と準同型写像

## Homomorphic Mapped Types　とは
**Homomorphic Mapped Types** は、Mapped Types の一種で、オプショナル修飾子`?`や`readonly`などの修飾子をそのままに、オブジェクトの型の構造を保持したまま新しい型を宣言できることが特徴的です。
書き方にMapped Types との違いは特になく、`{[P in X]: Y}`のように記述しますが、これがHomomorphic Mapped Types となる条件は、**`X`の部分がオブジェクトのプロパティキーの型となっていること**です。
つまり、Homomorphic Mapped Types は、`{[P in keyof T]: U}`の形で表されるものとなります。

`T`の部分にオブジェクトのキー（のユニオン型）が渡されると、宣言されるオブジェクトの型には`T`と同じプロパティキーが含まれることになります（プロパティの型自体は`U`の部分によって変化します）。

## Homomorphic Mapped Types の性質

### `?`や`readonly`の保持
以下の例では、Mapped Types `{[P in X]: Y}`の`in X`の部分に`keyof`を使ってオブジェクトのキーを指定した場合には`?`や`readonly`が保持され、オブジェクトのキーを単にユニオン型で指定した場合には修飾子が保持されないことを確認できます。
```ts
type Obj = {
  readonly num: number
  str?: string
}

type Homomorphic = {
  [P in keyof Obj]: Obj[P]
}
// type Homomorphic = {
//     readonly num: number;
//     str?: string | undefined;
// }

type keyStr = "num" | "str"

type NonHomomorphic = {
  [P in keyStr]: Obj[P]
}
// type NonHomomorphic = {
//     num: number;
//     str: string | undefined;
// }
```

### Union Distribution
Homomorphic Mapped Types には、Conditional Types と同様にユニオン型を分配する働き（Union Distribution）があります。

https://qiita.com/axoloto210/items/627b019995b81d918f7d

型引数`T`をとるHomomorphic Mapped Types `HMT<T>`に対してユニオン型`X | Y`を渡すと、`HMT<X | Y>`は`HMT<X> | HMT<Y>`のようにユニオン型が分配される形となります。

型引数`T`をとるHomomorphic Mapped Types `HMT<T>`と通常のMapped Types `MT<T>`のそれぞれにユニオン型を渡してみます。
```ts
type Obj = {
    readonly num: number
    str?: string
  }
  
type Obj2 = {
    foo: string
    bar: number
}

type MT<X extends PropertyKey> = {
[P in X]: string
}

// type UnionMT = {
//     num: string;
//     str: string;
//     foo: string;
//     bar: string;
// }
type UnionMT = MT<keyof Obj | keyof Obj2>

type HMT<T> = {
    [P in keyof T]: string
}

//type UnionHMT = HMT<Obj> | HMT<Obj2>
type UnionHMT = HMT<Obj | Obj2>
```
Mapped Types `MT<X extends PropertyKey>`に`keyof Obj`と`keyof Obj2`のユニオン型を渡した場合にはUnion Distribution は働かずに、2つのオブジェクトのプロパティキーを合併したオブジェクト型になっています。

一方でHomomorphic Mapped Types `HMT<T>`に`Obj`と`Obj2`のユニオン型を渡した場合にはUnion Distribution が働き、`HMT<Obj> | HMT<Obj2>`とユニオン型が分配されていることがわかります。


## Homomorphic Mapped Types と準同型写像
構造を保存する写像である、準同型写像(homomorphic mapping)が名前の由来となっているようです。
Homomorphic Mapped Types`{[P in keyof T]: U}`は、作成元となるオブジェクト型`T`と全く同じプロパティキーをもつため、オブジェクトの構造が保存されていることを**homomorphic**と表しているようですね。

>A mapped type of the form { [P in keyof T]: X } is homomorphic with T (because it has the same set of properties as T) and now preserves the optional and readonly modifiers as they exist on the properties in T.

https://github.com/microsoft/TypeScript/pull/12563

ちなみに、ユニオン型を分配する働きが追加されたころは、Isomorphic Mapped Types と呼ばれていたようです。

https://github.com/microsoft/TypeScript/pull/12447
AtCoderで速い言語と遅い言語がある理由を知らなかったので勉強したメモ

# 概要
プログラミング言語には処理速度が速い言語と遅い言語があります。
この記事では処理速度に差が出る理由について解説しています。

# 背景
自分は過去に9か月ほどAtCoderをやっていた時期があります。
その時はPyPyでコードを書いていました。
もともとPythonで勝負しようとしていたのですが、実行速度が極端に遅くTimeoutを連発していたためです。
で、これまたよくわかってなかったのですが、どうやらPyPy使うと速くできるということを聞いてPyPyに切り替えました。
また、そのとき同時に知ったのはPyPy ←→ Python間だけでなく、プログラミング言語全般において言語よって実行速度に大きく差があるということでした。例えばPyPyで書くとタイムアウトになってしまうようなアルゴリズムでも、C++であればゴリ押しできてしまうことがあるほどです。

はい、そして自分はこのように言語によって速度に差が出る理由について、ろくに勉強せずに何年も過ごしてしまいました。
さすがに恥ずかしくなったのでこの度勉強することにしました。

# 記事の目的
自分と同じように言語間で速度に差がある理由をモヤモヤにしたままの人はきっといるはずです。

この記事を読んでモヤを晴らしていただくことをこの記事の目的としています。

# プログラミング言語の実行速度とコンパイルプロセスの比較
プログラミング言語の実行速度は、ソースコードがどのように機械語（すなわち、実際の計算処理を担うCPUが理解可能なフォーマット）に変換され、実行されるかによって大きく異なります。

## 実行速度に影響を与える要因
1. タイミング：プログラムの機械語への変換が行われるタイミングには、事前と実行時の2つがあります。もちろん、事前に変換されている方が、実行時に変換のためのオーバーヘッドを喰わずにすむので速くなります。
2. 単位：変換が行われる単位も重要です。一括で変換する場合と、命令単位や関数単位で逐次的に変換する場合があります。変換単位が細かくなるほど、変換処理の回数が増えることになり、すなわち変換処理のオーバーヘッドを喰いやすくなります。
3. 最適化：各言語が実行時に行う最適化の程度も実行速度に影響します。高度な最適化が行われると、実行速度が向上します。


## 各言語のコンパイルプロセスと実行速度の比較
以下に、主要なプログラミング言語のコンパイルプロセスと実行速度を示したスライドをご紹介します。
![Screenshot 2024-07-15 163432.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490325/aaa92962-5b31-4615-c01c-d02df0b81c2c.png)


上記のスライドについていくつか補足説明を添えます。

## 中間言語について
中間言語（Intermediate Language）とは、ソースコードと機械語（CPUが理解する命令）の中間段階で使用される言語です。プログラミング言語の実行において、中間言語を使用することにはいくつかのメリットがあります。

### 中間言語のメリット
1. 全体的な労力を減らす：
    * 一貫性の確保：中間言語を使用することで、プログラムの中間段階が統一され、各プラットフォームでの動作が一貫します。開発者は、一つの共通フォーマットに対して最適化を行えばよいので、異なるプラットフォームごとの調整作業が大幅に削減されます。
    * 再利用性：同じ中間言語を使用する複数の言語（例：JavaとScala）は、同じ仮想マシン（VM）上で動作できます。これにより、VMの開発や最適化の労力が分散され、効率的になります。
2. 専門性の分離：
    * 言語設計とVM開発の分離：言語設計者は、言語の文法や構文、標準ライブラリの設計に集中できます。一方、VM開発者は、中間言語をいかに効率よく実行するかに専念できます。この分業により、それぞれの専門分野に特化した開発が可能となり、全体の品質と効率が向上します。

### 中間言語の具体例
* Javaバイトコード：JavaプログラムはまずJavaコンパイラによってJavaバイトコードという中間言語に変換されます。このバイトコードはJVM（Java仮想マシン）上で実行され、各プラットフォームに合わせて最適化されます。
* .NETのCIL（Common Intermediate Language）：C#やVB.NETなどの言語は、.NETコンパイラによってCILにコンパイルされ、共通言語ランタイム（CLR）で実行されます。

## 最適化について
最適化は、プログラムの実行速度やメモリ使用量を改善するために行われるプロセスです。特に競技プログラミングのような環境では、**ホットスポットの最適化**が実行速度に大きな影響を与えます。

ホットスポットの最適化は、プログラムの中で頻繁に実行される部分（ループや再帰的な関数呼び出しなど）を特定し、機械語のキャッシングを行ったり、その他のポイントで重点的に最適化することを言います。これにより、全体のパフォーマンスが大幅に向上します。
【個人開発_#4】Googleログイン機能を実装

前回は、UI部分の実装を進めました。
今回は、Googleログイン機能を実装していこうと思います。

今回のアプリはGoogleログインだけに絞って開発をしようと思います。

ほとんどこちらの記事を参考にさせていただきました。

https://qiita.com/k-sukesakuma/items/4b56b9e81c1788d38440

実際にこちらの記事を参考に自分のプロジェクトに合わせた箇所だけピックアップします。

まだ、UIが変わるかもしれませんが一旦トップページのところでログインボタンとログアウトボタンを実装してみます。

```javascript
'use client';
import Footer from '@/components/Footer';
import Image from 'next/image';
import Button from '@/components/Button';
import Header from '@/components/Header';
import { useSession, signIn, signOut } from 'next-auth/react';

export default function Home() {
  const { status } = useSession();

  return (
    <>
      <Header />
      // 省略
          <h1 className="text-2xl text-center mt-6">協力隊の輪</h1>
          <div className="text-center mt-10">
            {status === 'authenticated' ? (
              <Button onClick={() => signOut()}>ログアウト</Button>
            ) : (
              <Button onClick={() => signIn('google', {}, { prompt: 'login' })}>ログイン</Button>
            )}
          </div>
　　　　　　　　　　　　// 省略
      <Footer />
    </>
  );
}
```

NextAuthから必要なフックをインポートします。
```javascript
import { useSession, signIn, signOut } from 'next-auth/react';
```

statusによってボタンを出し分けます。
未ログインの際には、`unauthenticated`となり、ログイン後は`authenticated`となります。
```javascript
{status === 'authenticated' ? (
  <Button onClick={() => signOut()}>ログアウト</Button>
) : (
  <Button onClick={() => signIn('google', {}, { prompt: 'login' })}>ログイン</Button>
)}
```


ログイン後はcokkieの`next-auth.session-token`にトークンが保存されるようです。
![CleanShot 2024-07-14 at 20.49.45@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/768eddf1-fe95-5bac-4245-68a50cb39567.jpeg)

ログイン後の、Googleに登録されている情報は下記のように表示させることが可能です。
ヘッダー部分に画像を表示させてみます。
```javascript:Header/index.tsx
'use client';
import { useSession } from 'next-auth/react';

export default function Header() {
  const { data: session, status } = useSession();

  return (
    {status === 'authenticated' ? (
    <Link href="#">
      <Image src={session.user?.image ?? ``} alt="logo" width={45} height={45} />
    </Link>
    ) : (
    <Link href="/login" className='className="px-4 py-2 bg-main-500 text-white rounded-md"'>
      ログイン
    </Link>
    )}
  )
```
`name`や`email`なども表示させることが可能です。

https://next-auth.js.org/getting-started/client

![CleanShot 2024-07-15 at 16.35.46@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/6426bf13-578f-5350-5c37-c810cc6d0c32.jpeg)


## まとめ
とても参考になるQiita記事がありスムーズに実装ができました。
次回は、SupabaseとPrismaを導入して、データの永続化をしていこうと思います！
html2canvasでモバイルサイトのスクリーンショットを撮る方法

# やりたいこと
スマホでモバイルサイトを開いて、Webページ全体のスクリーンショットを撮りたい

# やり方
html2canvasライブラリを使いやりました。
ユーザーから見るとスクリーンショットをそのまま撮るように見えますが、裏ではhtmlファイルのDOMツリーやCSSツリーを解釈してcanvasで描画するみたいなことをしました。

```ruby:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML to Canvas</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
</head>
<body>
    <div id="capture" style="width: 100%; height: 2000px; background: lightblue; text-align: center; line-height: 200px;">
        <h1>Hello, World!</h1>
        <h2>長いサイトだよ</h2>
        <h3>高さ2000px</h3>
    </div>
    <button id="download">Download as Image</button>

    <script>
        document.getElementById('download').addEventListener('click', function() {
            html2canvas(document.body).then(function(canvas) {
                // Convert the canvas to a data URL
                var link = document.createElement('a');
                link.href = canvas.toDataURL('image/png');
                link.download = 'capture.png';
                // Trigger the download
                link.click();
            });
        });
    </script>
</body>
</html>

```
結果はこんな感じです。
スマホ画面ではスクロールしないと一番下の要素が見れないですが、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/9987ffe2-e8a5-a720-b2a3-db98ff710fd2.png)

ボタンクリックしたらWebページを上からしたまで撮りました。

![capture (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/941ddd14-42bc-e959-ed97-5dff4876cd99.png)

:::note info
全画面で撮りたい場合はbody指定ですが、
html2canvas(document.body)
一部しか撮りたい場合はその要素だけ指定しても大丈夫です！
html2canvas(document.getElementById('capture'))
:::

# 参考サイト
https://qiita.com/youwht/items/8b681a856f59aa82d671
dockerメモリ管理 No space left on device

```
docker system prune -a 
```
全て削除してくれる

```
docker volume prune
```
ボリューム削除

https://docs.docker.jp/config/pruning.html

ディスク容量確認
```
docker system df
```

### docker volume ls -qf dangling=true
dangling フィルタはコンテナから参照されていない（dangling＝宙ぶらりんな）ボリュームに一致します。

コンテナから参照されていない宙ぶらりんなvolume削除
```
 docker volume rm $(docker volume ls -qf dangling=true)
```

https://docs.docker.jp/v1.11/engine/reference/commandline/volume_ls.html
アプリ開発の工夫としてPlantUMLを使用する

## 概要
アプリ開発の工夫として、
私はPlantUMLを使用して設計を図示することが多かったです。
簡単なCRUD処理などシンプルな場合は、
そもそも図示する必要はないため効率が悪いです。
重たいバッチ処理のようなどうしても処理が複雑になってしまうような場面では、
実装や不具合調査の際にはかなり重宝していました。

具体的にどのような場合に、どのような図を作成するのか記載します。

## アクティビティ図
例えば下記の設計って頭の中で組み立てるの難しくないでしょうか？
(存在しない処理を頑張って書いたつもりです。)
1. 毎週月曜日午前2時にバッチ起動
1. ユーザテーブルから有効ユーザ全件取得
1. 有効ユーザに紐づく先週の購入履歴を取得
1. 購入履歴が存在しない場合2~4週間前の購入履歴を取得
1. 過去4週間購入履歴が存在しない場合各ユーザにセール情報をメールで送信する
1. 有効ユーザ1000件毎に並列処理を行う※4並列
    1. 購入金額の合計が閾値を超えるかチェックする
    1. 閾値を超える場合
        1. ゴールド会員の場合処理不要
        1. シルバー会員の場合ゴールド会員に昇格する
        1. ブロンズ会員の場合シルバー会員に昇格する
    1. 閾値を超えない場合もしくは1週間の購入履歴が存在しない場合
        1. ゴールド会員の場合シルバー会員に降格する
        1. シルバー会員の場合ブロンズ会員に降格する
        1. ブロンズ会員の場合処理不要
1. 後続処理を実行する

PlantUMLのアクティビティ図を作成します。
```plantuml
@startuml
:毎週月曜日午前2時にバッチ起動;
:ユーザテーブルから有効ユーザ全件取得;
:有効ユーザに紐づく先週の購入履歴を取得;
if (購入履歴) then (存在しない)
  :2~4週間前の購入履歴を取得;
    if (過去4週間の購入履歴) then (存在する)
    else (存在しない)
      :各ユーザにセール情報をメールで送信する;  
    endif  
endif

repeat
    :1000ユーザ毎に並列処理を行う※4並列;
    if (購入金額の合計) then (閾値以上)
      :ゴールド会員の場合処理不要
      シルバー会員の場合ゴールド会員に昇格する
      ブロンズ会員の場合シルバー会員に昇格する;
    else (閾値未満)
      :ゴールド会員の場合シルバー会員に降格する
      シルバー会員の場合ブロンズ会員に降格する
      ブロンズ会員の場合処理不要;
    endif
repeat while (有効ユーザを全件処理するまで繰り返し)
:後続処理を実行する;
@enduml
```

どうですかね。
例えで出した設計が微妙なせいで、
効果を伝えきれていない気がします。

不具合調査の例も出しておきます。
* 会員のランクが更新されていないユーザがいる
    →1000件単位でリカバリをしなければならない可能性が高いとすぐわかる
    ※トランザクションの実装にもよりますが
* 会員ランクは更新されているがメールが送信されていない
    →下記2点の調査から即開始できる
    先週の購入履歴が存在しないユーザーは存在いるか
    過去2~4週間の購入履歴が存在しないユーザは存在いるか

## まとめ
今いる案件では自分の頭の中を整理する時や、
他の実装者との認識共有のために使用することが多いです。
あくまで内部資料として外には出さないため、
そこまできっちり作ったことはないですが、
処理の複雑さによっては作成必須にしても良いのではと思っています。
新規参入者が多いプロジェクトでは効率良く把握できるはず。

最期にソースを載せておきます。
```text
@startuml
:毎週月曜日午前2時にバッチ起動;
:ユーザテーブルから有効ユーザ全件取得;
:有効ユーザに紐づく先週の購入履歴を取得;
if (購入履歴) then (存在しない)
  :2~4週間前の購入履歴を取得;
    if (過去4週間の購入履歴) then (存在する)
    else (存在しない)
      :各ユーザにセール情報をメールで送信する;  
    endif  
endif

repeat
    :1000ユーザ毎に並列処理を行う※4並列;
      if (購入金額の合計) then (閾値以上)
        :ゴールド会員の場合処理不要
        シルバー会員の場合ゴールド会員に昇格する
        ブロンズ会員の場合シルバー会員に昇格する;
      else (閾値未満)
        :ゴールド会員の場合シルバー会員に降格する
        シルバー会員の場合ブロンズ会員に降格する
        ブロンズ会員の場合処理不要;
      endif
repeat while (有効ユーザを全件処理するまで繰り返し)
:後続処理を実行する;
@enduml
```
ユーザー定義型ガード（型述語）で少しでも型安全に

## 型ガード
型ガードとは`if(typeof value === 'string')`のように型情報による条件分岐や`in`演算子などによってブロック内の型を絞り込む機能を指します。
この絞り込み部分をユーザー（実装者）が関数の形で作成して、型ガードとして利用するのがユーザー定義型ガード（型述語）です。
## ユーザー定義型ガード（型述語）
ユーザー定義型ガードとは、条件を満たした時に関数の引数の型をユーザーが設定した型としてTypeScriptのコンパイラに扱わせる機能です。
`as`による型アサーションや`any`型と同様にTypeScriptの型安全性を破壊しうる危険な機能ですが、確認すべき範囲が`as`や`any`に比べて明確であることから、これらの機能をやむを得ず使用する場合にはユーザー定義型ガードの使用が推奨されています。
## `引数 is 型`によるユーザー定義型ガード
関数によって型の絞り込みを行いたい場合には、ユーザー定義型ガードが使用できます。
とくに、`unknown`型の値を扱うのに便利な機能となっています。
```ts
type Fish = {
  name: string
  age?: number
}

function isFish(fish: any) {
  if (fish === null) {
    return false
  }
  return (
    typeof fish.name === "string" &&
    (typeof fish.age === "number" || typeof fish.age === undefined)
  )
}

const tuna: unknown = {
  name: "tuna",
  age: 5,
}

if (isFish(tuna)) {
  console.log(tuna.age) //'tuna' is of type 'unknown'.ts(18046)
}

```
上のコード例のように関数による型の条件分岐を行なっても、TypeScriptのコンパイラは型の絞り込みを認識できず、コンパイルエラーとなってしまいます。
```
 'tuna' is of type 'unknown'.ts(18046)
```
そこで、関数の返り値の型に`fish is Fish`とつけることで、関数が`true`を返した場合にはコンパイラに引数として渡した変数の型は`Fish`型であると認識させることができます。
ここの実装を間違えると誤った型をコンパイラが認識したままの状態になり、型安全性が損なわれるので注意が必要です。
```ts
type Fish = {
  name: string
  age?: number
}

function isFish(fish: any): fish is Fish {
  if (fish === null) {
    return false
  }
  return (
    typeof fish.name === "string" &&
    (typeof fish.age === "number" || typeof fish.age === undefined)
  )
}

const tuna: unknown = {
  name: "tuna",
  age: 5,
}

if (isFish(tuna)) {     // const tuna: unknown
  console.log(tuna.age) // const tuna: Fish
}

```
ユーザー定義型ガードを追加した後のプログラムでは型エラーが出なくなっており、`if(isFish(tuna))`に書かれている変数`tuna`は`unknown`と認識されていますが、ユーザー定義型ガードを通った後の`tuna`変数が使用されている箇所`console.log(tuna.age)`では、`Fish`型として推論されるようになっています。
## `asserts 引数 is 型`によるユーザー定義型ガード
関数が例外を投げて終了しない可能性がある場合には、`asserts 引数 is 型`の構文によるユーザー定義型ガードが使えます。
こちらは関数が`true`を返した場合に型を強制するのではなく、関数が最後の処理まで到達した場合に型を強制します。
```ts
function isNumber(value: unknown): asserts value is number {
  if (typeof value !== "number") {
    throw new Error()
  }
  return
}

const value: unknown = 314
try {
  // const value: unknown
  console.log(value) // 314

  // const value: unknown
  isNumber(value)

  //const value: number
  console.log(value.toString(16)) //　"13a"
} catch (error) {
  console.log("error occurred")
}

```
`try`ブロック内では`isNumber`より後ろの箇所での`value`の型が`number`型として推論されています。

ユーザーが「`isNumber`が正常終了しているのならば`value`の型は`number`型である」と保証しているわけですが、ここの保証の部分、つまりユーザー定義型ガードの実装に誤りがあると型安全性は大きく損なわれてしまうため、慎重に使用する必要があります。

`any`や型アサーションに比べると、ユーザーが責任を負うべき箇所が関数ないのみと明確なので、やむを得ない場合にはユーザー定義型ガードの使用を先に検討することが推奨されているわけですね。

https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates

https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
【Power Apps】ユーザーを複数取得できるコネクタのアクションのまとめ

# ユーザーを複数取得できるコネクタのアクションのまとめ

取得したユーザー一覧のメールアドレスをコピーしたり、メールアドレスを他のコネクタのアクションに入力することでユーザーの追加作業を大幅に短縮できるかもしれません。

この記事は、[Power Apps Advent Calendar 2023](https://adventar.org/calendars/7047) 12月4日担当分の記事です。

## ユーザー検索

一番シンプルなユーザー検索でユーザーを選択する方法です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/f23e53f0-7a6f-29d5-7c64-9c7f910ece77.png)

https://powerplatformnikki.com/office365search/

複数選択の許可、検索の許可をオンにすることで、ユーザーの検索と複数ユーザーの選択が可能になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/b5319556-bb3b-8537-0ce0-cec1c709eeac.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/fe5f0e0d-c6f5-715f-005a-8cde2bc576b2.png)

## M365グループ（SharePointサイト＋Teamsのチーム）

M365グループを取得するには、ListOwnedGroupsV2とListGroupMembersを使用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/54b135b8-6cfb-844a-75be-faf01b789f37.png)

チームの所有者とユーザーで処理を分けることも可能です。

https://powerplatformnikki.com/office365groupslistownedgroups

https://powerplatformnikki.com/office365groupslistgroupmembers

## Teamsのチームで設定されているタグのメンバー

TeamsコネクタのGetTagsとGetTagMembersアクションを用いて、Teamsのタグに設定されているメンバーを取得することもできます。

Teamsでタグを設定する必要がありますが、この記事で紹介しているコネクタのアクションを使用してタグを設定すると楽に設定ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/d5650b38-2311-6507-4483-4b3edb47b7a0.png)

https://powerplatformnikki.com/teamsgetallteamsgetteam/

https://powerplatformnikki.com/teamsgettagsgettagmembers/

## Power Appsのアプリのユーザー

作成者向けPowerAppsコネクタのGetAppsアクションとGetAppRoleAssignmentアクションを使用することで、アプリのユーザーを一覧表示することができます。

アプリをコピーする際に権限はコピーされないので、これらのコネクタを使用してコピーするといいかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/137b74ba-2dc5-6693-9c44-2b3509f62989.png)

https://powerplatformnikki.com/papps4makersgetapps/

https://powerplatformnikki.com/papps4makersgetapproleassignment/

## Power Automateのフロー所有者

Power Automate ManagementコネクタのListMyFlowsアクションとListFlowOwnersアクションを使用することで、フローの所有者を一覧表示することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/65c59425-e8ad-76fb-280b-6d9f45419b5d.png)

https://powerplatformnikki.com/pautomatemnglistmyflows/

https://powerplatformnikki.com/pautomatemnglistflowowners/

## 活用方法

### コネクタのアクションで取得したメールアドレスをコレクションに格納するアプリの作り方

https://powerplatformnikki.com/storeuserstocollection/

### アプリの権限を便利に変更するアプリの作り方

https://powerplatformnikki.com/modifyappflowusers/

## 元記事

https://powerplatformnikki.com/getusersactions/
【k8s】GitOps構築してsecret managementもした話 〜ArgoCD編〜


こんにちは。
UniProjectのあかつきゆいとです。
今回は、GitOpsでシークレットごちゃごちゃする話です。

# 背景

うちのサークルでは、Mediawikiをサークル内Wikiにしています。
公式のDockerイメージだと、extention周りとかが納得いかないので、Dockerイメージも自作して、GitHubにも載せていますね。(GitHubは、一番下に載っけてます。)
そこで、k8sにわざわざ毎回デプロイするためにごちゃごちゃするのがめんどくさいわけですよ。
なので、GitHubにプッシュしたら、いい感じにK8sに乗っけてくれるやつを構築しました！！

# 前提

環境はこちらです。

- OS: Ubuntu24
- microk8s
- Proxomox VM

# 準備

今回準備するものは、

- ArgoCD(GitOps)
- SealedSecret

の2つです

## ArgoCD

### インストール

ArgoCDのマニフェストファイルを直で引っ張ってきましょうか。

```sh
# ネームスペースを作成
kubectl create namespace argocd
# マニフェストファイルを適用
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
```

ここから、ダッシュボードにアクセスしていきましょう。
ただ、うちのサークルは、サークルメンバーの家で動いているので、リバースプロキシを通しましたね。

普通の人は、こちらのコマンドでポートフォワードを...

```sh
kubectl port-forward svc/argocd-server -n argocd 8080:443
```

これで、localhost:8080で接続できますね。

### ログインする

ユーザーIDはadmin、パスワードは以下のコマンドで、初期PWが取れます。

```sh
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
```

### GitHubとの連携

GitHubとは、左側の歯車から、Repogitory > Connect Repo Using HTTPSをクリック。
必要事項を入力します。

### デプロイ

リポジトリの一覧から、右の...をクリックし、Create Applicationをクリック。
プロジェクトネームはdefault、Sync policyはAUTOで構いません。
Pathには、manifestsファイルのあるディレクトリを指定します。

これで、デプロイが完了するはずですね。

# 最後に

今回はここまでです。
次回は、SealedSecretの設定の話を書きます...

GitHubはこちらです。

<https://github.com/UniPro-tech/Mediwaiki>
SourcetreeシステムトレイにSSHエージェント(Pageant)が起動しました。キーを(必要分)読み込ませた後、再試行を押してください。に遭遇した

# この記事について
下画像のような警告に遭遇したので、調べた事や解決方法をメモとして書いています。誤字脱字や間違っている部分があればコメントで教えていただけると幸いです。

![スクリーンショット 2024-07-15 145958.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/054550c0-5b0d-b9fe-8d57-fb4e25799f4c.png)

:::note warn
注意点
自分のPCがWindowsなので他機種で解決できるかは分かりません。
また、ndows11バージョンなのでファイルの開く場所が違う可能性もあります。
:::

# 参考にした記事

https://akamist.com/blog/archives/343

# 解決方法
- 警告の確認

![スクリーンショット 2024-07-15 145958.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/054550c0-5b0d-b9fe-8d57-fb4e25799f4c.png)
`Pageant`にキーを読み込ませて(以下略)と書いてあるので、キーの再読み込みを行います。

***
- Sourcetreeを開く

開いていない方はSourcetreeを起動してください。

![スクリーンショット 2024-07-15 160257.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/b3f43a03-c4b1-1577-1cbf-9715d9c6ed8f.png)


***

- Pagentを開く

通知領域の右下側にある`^`をクリックします。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/69468f70-5c03-044e-3bdf-fcf42d3bb7c0.png)

クリックすると以下のメニューが出るのでパソコンのアイコンをクリックします。
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/b15b4318-cf8d-b702-e250-5327162af214.png)

`Pagent`を起動するとこのような画面になるので、左下にある`Add Key`を押します。
※元々書いてある部分を隠しているので少し図がおかしいです。
![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/add76c1a-2d99-de27-8a0f-b0af0c9a99a8.png)

`Add Key`を押すと、画像の様に`PuTTY Private Key Files`のファイル名を指定する必要があるので、ファイル名を指定します。`ppk`という名前でファイル検索をすれば見つかると思います。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/1f526275-1ed6-2dd9-c7cb-4184762ce0c0.png)

鍵のファイル名を指定したら、`開く`を押してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/45f97908-6fd6-f7ca-fe46-2a70e11023c1.png)

後はSourcetreeを再起動して動作確認するだけです。
自分は上記の内容を行って解決する事が出来ました。
B-Love Token Price Prediction for 2024: A Deep Dive

Predicting the future price of any cryptocurrency, including B-Love, is a complex endeavor fraught with uncertainty. However, by analyzing past performance, market trends, and underlying fundamentals, we can attempt to forecast potential price movements for 2024.

### Understanding B-Love Token and the Crypto Market

Before diving into predictions, it's essential to understand the B-Love token and the broader cryptocurrency landscape. B-Love is a digital asset designed to power the B-Love Network, a platform aimed at revolutionizing content creation and consumption. Its price is influenced by factors such as:

*   **Market Supply and Demand:** The fundamental economic principle governing asset prices.
    
*   **Platform Adoption:** The growth and expansion of the B-Love Network directly impact token value.
    
*   **Token Utility:** The versatility and usefulness of the B-Love token within the ecosystem contribute to its perceived value.
    
*   **Market Sentiment and Investor Confidence:** The overall mood of the cryptocurrency market and investor confidence in B-Love significantly impact the token's price.
    
*   **Regulatory Environment:** The regulatory landscape for cryptocurrencies plays a crucial role.
    

The cryptocurrency market as a whole is highly volatile, influenced by factors like global economic conditions, technological advancements, and regulatory changes.

Website: [https://www.vevioz.com/blovecoinprice](https://www.vevioz.com/blovecoinprice)
Bootstrapの意味をchatGPTに聞いてみた。

# Bootstrapの意味と由来について

最近、Laravelのプロジェクトを進めている際に「Bootstrap」という言葉に混乱しました。同じ名前が使われているものの、実際には異なるものを指していることに気づきました。ここでは、「Bootstrap」という単語の意味と由来について整理し、説明します。

## LaravelのBootstrap

Laravelの「bootstrap」は、フレームワークの初期化や設定を行うためのディレクトリです。このディレクトリには、アプリケーションの起動時に必要なファイルや設定が含まれています。

- **bootstrap/app.php**: Laravelアプリケーションのインスタンスを作成し、必要な設定やサービスプロバイダーを読み込むファイルです。
- **cache**: アプリケーションのキャッシュファイルが格納されるディレクトリです。ルートキャッシュ、コンフィグキャッシュなどが含まれます。

## WEBデザインのBootstrap

一方、WEBデザインに使用される「Bootstrap」は、Twitter社が開発したオープンソースのフロントエンドフレームワークです。Bootstrapは、レスポンシブデザインを簡単に実装できるようにするためのCSS、JavaScriptのライブラリを提供します。

- **CSSフレームワーク**: グリッドシステム、ボタン、フォーム、ナビゲーションバーなど、さまざまなスタイルを簡単に適用できます。
- **JavaScriptコンポーネント**: モーダル、ドロップダウン、ツールチップ、アラートなどのインタラクティブなコンポーネントを提供します。

## Bootstrapという単語の由来

「bootstrap」という単語は、元々は物理的な「ブーツのストラップ」を指します。これはブーツの後部についている小さなループで、これを引っ張ることでブーツを履きやすくするためのものです。この物理的な意味から派生して、以下のような抽象的な意味でも使われるようになりました。

### コンピュータサイエンスにおけるBootstrap

コンピュータサイエンスの分野では、「bootstrap」はシステムが自力で立ち上がる（自己初期化する）プロセスを指します。特に、コンピュータの電源を入れたときに最初に実行される一連の操作（ブートストラッププロセス）を意味します。

#### ブートストラッププロセスの例

1. **BIOS/UEFI起動**: 電源を入れると、まずBIOS（Basic Input/Output System）やUEFI（Unified Extensible Firmware Interface）が起動し、ハードウェアの初期化を行います。
2. **ブートローダーの読み込み**: 次に、BIOS/UEFIはブートローダーをメモリにロードします。ブートローダーはオペレーティングシステムのカーネルを読み込む役割を持ちます。
3. **カーネルの起動**: ブートローダーはカーネルをメモリにロードし、実行を開始します。これによりオペレーティングシステムが起動します。

### ソフトウェア開発におけるBootstrap

ソフトウェア開発において、「ブートストラップ」は、システムやアプリケーションが自己初期化し、動作を開始するための最初のステップを指します。

### フロントエンドフレームワークのBootstrap

フロントエンドフレームワークの「Bootstrap」は、Twitter社が開発したもので、ウェブデザインを迅速に開始するための「スタートキット」としての役割を果たします。名前の由来は、開発者が簡単にウェブサイトのデザインを「立ち上げる」ことができるようにするという意味合いから来ています。

## まとめ

- **Laravelのbootstrap**: フレームワークの初期化や設定を行うためのディレクトリ。
- **WEBデザインのBootstrap**: レスポンシブデザインを実現するためのCSS、JavaScriptフレームワーク。
- **物理的な意味**: ブーツのストラップ（履きやすくするためのループ）。
- **コンピュータサイエンス**: システムが自己初期化するプロセス。
- **ソフトウェア開発**: システムやアプリケーションが動作を開始するための初期化手順。

このように、「bootstrap」という単語は元々の物理的な意味から派生して、さまざまな分野で「自己初期化」や「立ち上げ」という概念を表すために使われるようになりました。今後は、これらの違いを意識しながらプロジェクトを進めていきたいと思います。

※ちなみに初投稿であり、私が記述したのはここだけで、上記の説明およびマークアップはchatGPTがしてくれました、スカイネットももうすぐな気がしてなりません。
IX3110をファームウェアアップデートする

# はじめに
一般家庭にもよくあるIX3110ですが、以前は申請書に個人情報を書いてメールを送り付けなければ最新のファームウェアを入手できませんでした。
しかし最近では、いつからか個人情報を送りつけなくとも簡単にファームウェアを入手できるようになっているようです。

# ファームを入手する
[ここ](https://jpn.nec.com/univerge/ix/Download/index.html)から最新のファームウェアを入手します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/54766c10-49aa-83fc-5767-48ec26885d02.png)

2024/07/15現在、10.5.35が最新のようです。

ダウンロードしたzipの中身を解凍しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3283241/6eaf44cb-421e-7938-baf7-701e6a4c2d48.png)

# 作業を始める前に
作業に入る前に投入しているconfigのバックアップを取っておきましょう。
`show running-config`を実行することで、投入されているconfigが表示されます。

また、作業を開始すると数分間のダウンタイムが発生します。
そのため、バックアップ用のルーターに切り替えるか、通信断が発生することを周知してから作業を実施してください。


# TFTPサーバーを建てる
TFTPサーバーを構築します。
今回は[この記事](https://zenn.dev/kensan_gadget/articles/8a75d39841e318)を参考に構築しました。

https://zenn.dev/kensan_gadget/articles/8a75d39841e318

# アップデートする
ファームウェアの書き換えは5分くらいで終わります。
気長に待ちましょう

```shell
Router(config)# software-update tftp://[TFTPサーバーのIP]/[rapファイル]
% Downloading ...............
```
`% Software update completed.`と表示されるとファームウェアのアップデート完了です。

`show flash`を実行し、ファイルがフラッシュ内に存在するか確認し、完了したら再起動します。

```shell
Router# reload
Notice: The router will be RELOADED. This is to ensure that
        the peripheral devices are properly initialized.
Are you sure you want to reload the router? (Yes or [No]): y
```

ちゃんと`ix3100-ms-10.5.35.ldc`の方がメインになったら。
これでアップデートは完了です。

アップデート後はルーターの動作を確認し、問題がないかチェックしてください。通信が正常に行われているか、設定が正しく反映されているかなどを確認してください。
外部参照のあるsvnリポジトリのGit移行

昔調べた物。色々うろ覚え。

# 基本方針
外部参照が無ければ、`git svn`,`SubGit` などを使えば良いのですが、
これらは外部参照を無視してしまいます。

snv の外部参照の代用としては、git の SubModule が利用できます。


# SubModule の使い方

略

ググれば情報が出るのと、
記事とか読むより、実際に触って試した方が良いと思うので。


# 外部参照とSubModuleの差異

## 一部分を取り込むことが出来ない。

特定のフォルダのみを外部参照で取り込んでいる場合は、
参照されているフォルダを別のリポジトリとして分割する必要があります。


* 移行前のsvnリポジトリを分割した方が、処理時間が速かったです[^1]
* ライブラリ化など、別の方法で取り込む様に変えても良いかもしれません

[^1]:コミット数などにも依存すると思われますが。

## 最新を指す事が出来ない。
外部参照では、参照先のリビジョンとして、Head を指定できましたが、
SubModule では、参照するコミットを明示する必要があります。[^2]

[^2]:もっとも、最新を指す運用自体が、過去の状態に戻した際に不整合が出るなど不都合な点が多く、あまり良い運用ではありませんが


# SubModule の注意点

ツールによっては、SubModule に対応をしていない事があります。
開発ツールの案内などをしている場合は、SubModele に対応したツールかを、気にした方が良いでしょう。

# SubModuel を追加する、コミット位置に関して

簡単にやるなら、移行の直後に SubModule 追加すれば十分です。
ただし、移行前のコミットをチェックアウトした場合に、恐らくビルドは通らなくなりますが。

古いコミットでもビルドが通るようにするなら、svn で外部参照を設定したコミットで SubModule の追加を行い、
参照するリビジョンが


古いコミットでもビルドが通るようにするなら、
svn で外部参照の追加,変更を行ったコミットを洗い出し、
その各所で SubModule の追加,変更を行う必要があるでしょう。
export {};でファイルをモジュールとして扱わせる

## 先に結論
TypeScript では`export`か`import`が使用されている場合にモジュールとなり、そうでない場合にはスクリプトとして扱われます。

スクリプトではトップレベルで宣言された変数や型のスコープがグローバルなものとなるため、別のスクリプトファイルであっても同名の変数や型を宣言できません。

モジュールではスコープがファイル内に閉じるため、別のファイルであれば同名の変数や型を宣言可能です。

## スクリプトとモジュール
TypeScript（JavaScript）のファイルはスクリプトとモジュールに分類され、スコープや記法がそれぞれ少し異なります。

別のファイルでそれぞれ同名の変数や型を宣言すると、モジュールではエラーとならないが、スクリプトではエラーとなってしまう、といったことも起こります。

### スコープの違い
モジュールの場合には、変数のスコープはそのファイルの中に閉じており、外部ファイルから使用できるようにするには`import`・`export`文が必要になります。
モジュールのファイルであれば、それぞれのファイルで同じ名前の変数や型を定義してもエラーが出ることはありません。

スクリプトの場合には、変数や型のスコープはグローバルなものとなり、別々のスクリプトファイルに同じ名前の変数や型を宣言するとエラーが発生します。

>In particular, all scripts loaded onto the same page share the same scope—appropriately called the “global scope”—meaning the scripts had to be very careful not to overwrite each others’ variables and functions.

https://www.typescriptlang.org/docs/handbook/modules/theory.html

```ts:tuna.ts
type Fish = {
  name: string
  age: number
};

const fish: Fish = {
  name: "tuna",
  age: 5,
};
```
```ts:salmon.ts
type Fish = {
  name: string
  age: number
};

const salmon: Fish = {
  name: "salmon",
  age: 10,
};
```
上の２つのファイルでは、トップレベルで`Fish`型を宣言しています。
しかし、これらの2ファイルがスクリプトとして扱われている場合、以下のようなエラーが発生します。
```:tuna.ts でのエラー
Duplicate identifier 'Fish'.ts(2300)
salmon.ts(1, 6): 'Fish' was also declared here.
```
```:salmon.ts でのエラー
Duplicate identifier 'Fish'.ts(2300)
tuna.ts(1, 6): 'Fish' was also declared here.
```
`Fish`のスコープがグローバルスコープとなってしまっているため、型の重複エラーが発生しています。

ファイルがモジュールとして扱われていればこのエラーが発生することはありません。

## モジュールとして扱わせるには
### `export`や`import`を使用する
`export`文や`import`文が使用されている場合には、そのファイルはモジュールとして扱われます。

`export`や`import`は不要だが、モジュールとして扱わせたいというときには、`export {}`を記述しておく方法があります。
`export {}`は一見すると特に意味のない記述に見えますが、`export`自体は使われているのでファイルをモジュールとして扱わせることができるわけですね。

```ts:tuna.ts
type Fish = {
  name: string
  age: number
};

const fish: Fish = {
  name: "tuna",
  age: 5,
};

export {};
```
```ts: salmon.ts
type Fish = {
  name: string
  age: number
};

const salmon: Fish = {
  name: "salmon",
  age: 10,
};

export {};
```
先ほどの例とは`export {}`の有無だけが異なりますが、型エラーが発生しなくなりました。

### 基本はスクリプト扱い
`export`や`import`が使用されていない場合には、基本的にはスクリプトとして扱われます。

別のファイルに同名の変数や型を宣言してエラーが出てしまった場合には、スクリプトとして扱われていないかを確認してみると解決するかもしれませんね。
Mac mini 2011にProxmox VEをインストールする

仮想化基盤にはこれまでVMWare ESXiをよく使っていましたが、昨今のVMWare 事情から、別の仮想化基盤を使えるようにしておこうと思い立ち、手元で余っていたMac mini 2011にProxmox VEをインストールしてみました。

## Proxmox VEをインストールする
インストール先のマシンは、2011年もののMac miniです。Intel Mac が手元に欲しくて、発売当初に買った初号機が壊れた際に、2016年頃に中古で2号機を買い増ししたものです。既に Mac OSのサポート期限も過ぎたので、3年前頃にUbuntu を入れて時々使っていましたが、今回はこの古い Mac mini にProxmox をインストールしてみます。諸元としては、CPUが2.3GHzデュアルコアIntel Core i5、メモリとSSDは換装済で 16GB/500GBといった感じです。
https://support.apple.com/ja-jp/112007

Proxmox VEは、サイトから最新版のISOイメージをダウンロードします。2024年7月15日時点では8.2が最新でした。インストール用にはUSBメモリでも良かったのですが、手元にDVD-Rが余っていたので、こちらにISOイメージを書き込みました。Windows 11 だと、ISOイメージの書き込みが標準でできるので簡単でした。
https://www.proxmox.com/en/downloads

Mac mini に外付けDVDドライブを繋げて、電源ONする際に「OPTIONキー」（WindowsキーボードだとALTキー）を押しながら立ち上げると、ブートデバイスが選べるので、こちらでProxmox VEのインストーラを立ち上げます。rootのパスワードや固定IPアドレス、キーボード種別などを入力したら、メニュー通りに進むだけで、あっという間にインストールは完了します。

## Proxmox VEを使ってみる
インストールが終わったら、再起動してProxmox VEを動かします。コンソール上はLinux のログインプロンプトがCUIとして表示されている状態になります。他のPCのブラウザからインストール時に指定した固定IPアドレスを使って、https://xxx.xxx.xxx.xxx:8006/ にアクセスすると、Proxmox VEのコンソールにアクセスできます。インストール時に指定したパスワードを使って root アカウントでアクセスすれば、Proxmox VEの管理コンソールが使える状態になります。

早速仮想マシンを設定してみますが、それに先だってインストール用のISOイメージを登録しておくと便利でしょう。日頃使っているUbuntuのDesktop と Server のISOイメージを手元のPCにダウンロードしてから、Proxmox VEのlocal ディスク上の「ISOイメージ」の配下にISOイメージファイルをアップロードします。

ここまでできたら、あとは「VMを作成」で仮想マシンを作ります。メモリ 2GB、HDD 32GB、CPU 2コア/2ソケットとして、Ubuntu Desktop のISOイメージを指定して仮想マシンを起動すれば、あとは通常通りのUbuntu のインストーラが立ち上がってきます。

![ProxmoxVE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3785377/3c3e7eac-87af-4804-7ebf-22569dd6884f.png)

### 追記（2024-07-16）
Ubuntu Desktop 24.04 LTS をインストールしようと何度かトライしましたが、どうしてもインストーラが途中でフリーズしてしまうので、諦めて Ubuntu Desktop 22.04 LTS をインストールしました。こちらは問題無くインストールできました。
現時点では、do-release-upgrade では 24.04 LTS にアップグレードできないようなので、できるようになってから再度トライしようと思います。
FastAPI のルート Function は Async や Sync の選び方

前の理解が間違ったのでもう一度書いて置きます。書かないとたぶん明日はまた忘れるでしょう。

## 間違った理解
`def` に `async` を付けていれば、 FastAPI が自動的に新しいスレッド開いてその function を執行すると思いましたが
実際はこんなことじゃないんです。

```python
async def handler_get_some_data_from_db():
    async with async_read_session as session:
        try:
            result = await session.execute(myquery)
        finally:
            sesison.close()
            
@route.get("")
async def get_some_data_from_db():
  return await handler_get_some_data_from_db()
```

元々は `get_some_data_from_db` がサブスレッドで執行されると思いましたが、実際ではメインスレッドで執行されました。
メインスレッドで執行されたら、もし Blocking の状況が発生したら API も動けなくなるでしょう。


## そこでちょっと意外な発見

ルートの Function を `async def` から `def` に変わったら、動くは予定通りになりました。
先ほどのコードをちょっと修正したら
```python
async def handler_get_some_data_from_db():
    async with async_read_session as session:
        try:
            result = await session.execute(myquery)
        finally:
            sesison.close()
            
@route.get("")
def get_some_data_from_db():
  return asyncio.run(handler_get_some_data_from_db)
```

こんな感じになりました。
これでルートFunctionはちゃんと新しい作られたスレッドの中に執行されました。
良かった(T_T)

## あと一つ意外な発見
もし Function の中には asyncio や非同期に関することが一切なかったら、`def` だけでもメインスレッドで執行されます。
```python
def handler_get_some_data_from_db():
    with sync_read_session as session:
        try:
            result = session.execute(myquery)
        finally:
            sesison.close()
            
@route.get("")
def get_some_data_from_db():
  return handler_get_some_data_from_db()
```

こんな感じになったら `get_some_data_from_db` はメインスレッドで執行されます。

一体なぜだろ…いまはちゃんと理解する時間が残されていないので一旦暗記していきます。
Mapped Types による配列型・タプル型の保持

## Mapped Types
Mapped Types は`{ [P in X]: Y }`の形で宣言できる型で、`X`で指定したキーを持つオブジェクト型を宣言できます。
`X`に指定できる型はプロパティのキーとなれる型`string | number | symbol`の部分型に限られます。

ちなみに`string | number | symbol`には、`PropertyKey`という別名がついています。
```ts: typescript/lib/lib.es5.d.ts
declare type PropertyKey = string | number | symbol;
```
https://www.typescriptlang.org/docs/handbook/2/mapped-types.html

## 配列型・タプル型の構造の保持
型引数`T`をもち、`{ [P in keyof T]: U }`という形の型に`T`として配列型やタプル型を渡した場合、配列構造やタプル構造がそのまま保持されます。

これはTypeScript 3.1 から導入された仕組みのようですね。

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html#mapped-types-on-tuples-and-arrays

### 配列型の構造の保持
`type HMT<T> = { [P in keyof T]: string | undefined }`という型引数`T`をとる`HMT<T>`型について考えてみます。
以下のように`T`として配列を渡した場合と、型引数を介さずに直接`T`の部分に配列を記述した場合を比べてみると、得られる型が異なっていることがわかります。
```ts
type HMT<T> = {
    [P in keyof T]: string | undefined
}

//type ArrayHMT = (string | undefined)[]
type ArrayHMT = HMT<number[]>

// type ArrayMT = {
//     [x: number]: string | undefined;
//     length: string | undefined;
//     toString: string | undefined;
//     toLocaleString: string | undefined;
//     pop: string | undefined;
//     push: string | undefined;
//     ... 26 more ...;
//     readonly [Symbol.unscopables]: string | undefined;
// }
type ArrayMT = {
    [P in keyof number[]]: string | undefined
}

```
型引数を介した場合（`HMT<number[]>`）には、得られる型が配列型`(string | undefined)[]`となっています。

一方で、直接配列型を記述した場合には、配列ではなくインデックスシグネチャ`[x: number]: string | undefined;`に変換されており、配列操作用の関数名`pop`や`push`もプロパティキーに含まれてしまっています。

### タプル型の構造の保持
配列と同様のことがタプル型にも適用されます。
```ts
type HMT<T> = {
    [P in keyof T]: string | undefined
}

// type TuppleHMT = [string | undefined, string | undefined]
type TuppleHMT = HMT<[number, string]>

// type TupleMT = {
//     [x: number]: string | undefined;
//     0: string | undefined;
//     1: string | undefined;
//     length: string | undefined;
//     toString: string | undefined;
//     toLocaleString: string | undefined;
//     pop: string | undefined;
//     ... 27 more ...;
//     readonly [Symbol.unscopables]: string | undefined;
// }
type TupleMT = {
    [P in keyof [number, string]]: string | undefined
}
```
`[number, string]`型を型引数に渡した場合には、タプル構造が保持された状態の方が得られています。
一方、直接タプル型を記述した場合にはタプルの配列操作用の関数に加えて、タプルの要素番号`0`や`1`も含めて型情報に含まれてしまっています。

## おわりに
配列型やタプル型をMapped Types によって操作する場面で配列のラッパーオブジェクトのプロパティキーが顔を出してくると使いづらいため、型引数を介した操作の場合には配列やタプルの構造をそのまま保持するようにしてくれているみたいですね。

`{ [P in keyof T]: U }`という形のMapped Types はHomomorphic Mapped Types という名で呼ばれ、配列型・タプル型の他にも、オブジェクト型を受け取った場合に構造が保持されるような仕組みとなっています。
ITパスポート ネットワークの構成

・ネットワークの構成
・LAN
狭い範囲のネットワーク
同一敷地内や同一ビル内、同一のフロア内など

・WAN
物理的に離れたLAN同士を結ぶネットワーク

・パケット
データを小さく分割したもの
・パケット交換方式
通信回路を共有して効率良く通信を行う方式

・VoIP
音声をパケットに圧縮変換し、ネットワーク上でリアルタイムに伝送する技術
インターネットだけでなく、LANでも構築できる

・ネットワークの構成要素
・ハブ
PCに接続されているLANケーブルを束ねる集線装置
LANポートと呼ばれるLANケーブルを接続する複数の接続口がある

・スイッチングハブ
データのMACアドレスを解析して、特定のPCだけにデータを送信する装置

・MACアドレス
ネットワーク装置に割り振られた固有のアドレス

・L2スイッチ
データのMACアドレスを解析して、同じネットワーク内でデータの転送を行う装置

・ルータ、L3スイッチ
データのIPアドレスを解析して、異なるネットワークへデータを中継する装置

・ルーティング機能
最適な経路（ルート）を選択して中継する

・デフォルトゲートウェイ
LANとWANの境界に設置し、異なるネットワーク同士を接続する装置

・LANケーブル
ルータとハブ、ハブとPCなどを接続するケーブル

・PoE
LANケーブルを介して給電できる

・PLC
家庭内などに引かれている電気配線をデータの送受信に利用する技術

・WoL
遠隔地にあるPCなどの電源をネットワーク経由で起動させる機能
Chrome拡張の作成時にしょうもないミスで時間を溶かした

# はじめに
掲題の通り、Chrome拡張をつくっていたらしょうもないミスで時間を溶かしてしまったので自戒の念を込めて残しておきます。

作ろうとしていたのはPopup.html上のボタンクリックをトリガーにcontent_scriptsにメッセージを送り、content_scriptsで表示しているタブのDOMを操作するという拡張です。

なお、TypescriptおよびReactの練習もかねていました。
参考になるドキュメントもあったのでサクッと作れるはずだったんですが、
あるエラーが発生しました。

# Could not establish connection. Receiving end does not exist

どうもcontent_scriptsとpopup画面で通信がうまくいっていない模様。
ググってみるとメッセージをハンドルする関数でtrueを返す必要がある、とか
拡張機能を再読み込みした後にぺージのリロードをする必要がある、とか
ほかの拡張機能が原因の可能性があるので拡張機能をOFFにしてみる、とか
記事がでてきました。

先人がすでに踏み抜いて解決方法もたくさん出てくるみたいだし、何てことないだろう。
と思って記事を参考に悪戦苦闘していたらあっという間に時間を溶かしていました...

出てくる記事の解決法はすべて試したはずなのになぜ...
途方に暮れながら1から自分の書いたコードを隅々眺めているとあることに気が付きました。

んん？manifest.jsonのmatchesおかしくね？？

```

  "content_scripts": [
    {
      "matches": [
        "https://*//*",
        "http://*//*"
      ],
      "js": [
        "content_script.js"
      ]
    }
  ]
```

そう、なにをどう間違ったのかmatchesのURLのパスの区切りが`/`ではなく`//`になっていたのです！


以上、しょうもない書き間違いで時間を溶かしてしまった話でした。


# 参考
https://kitsune-gadget.hatenablog.com/entry/2022/05/07/181752#Could-not-establish-connection-Receiving-end-does-not-exist

https://qiita.com/sakaimo/items/5e41d6b2ad8d7ee04b12

https://zenn.dev/dotdotdot/articles/61174472b35ae0

https://qiita.com/Sukhwinder_Singh/items/a916f6e0a5d599b80d9b#%E5%BE%A1%E7%A4%BC
Ruby3.2をインストールするとき、libyamlが必要

## はじめに
Ruby3.2をインストールしようとした時にエラーが発生したので、解消方法をまとめていきます。

## 問題
```sh
$ rbenv install 3.2.0

BUILD FAILED
```

## 解決方法
Ruby3.2からlibyamlやlibffiのライブラリのソースコードの同梱が廃止されています。
libyamlをyumなどでインストール後、Rubyをインストールすると正常にインストールできます。

```sh
$ yum install libyaml-devel
```

## 参考
https://zenn.dev/fuuukeee3/articles/22caeb537cf1a6

https://www.ruby-lang.org/ja/news/2022/12/25/ruby-3-2-0-released/
物価資料のコード一覧PDFをCSVに変換してみた


工事積算するときに物価資料の平均値から材料の単価を採用しているけど、いちいち検索するのが面倒くさいので、自動化したい。その前段階として、両調査会が公表しているコード一覧をCSVに変換してみた。（最初からcsvで公表してくれると楽なんですがね）

## 建設物価
収録品目リスト（コードブック）「建設物価4編」のPDFをCSVに変換。

https://www.kensetu-bukka.or.jp/service/datafile/tankadata/

## 積算資料
建設物価の方とざっくり順番が似ている、コード表（分類順）のPDFを使用。

https://www.zai-keicho.or.jp/zk/sample/ecb/

# コード
pyMupdfを使用
## 建設物価
```python
import fitz
import pandas as pd
import requests
from tqdm import tqdm

pdf_path = 'local-kensetsu.pdf'
csv_path = 'kensetsu-bukka.csv'

data = []
pdf_url = 'https://www.kensetu-bukka.or.jp/wp-content/themes/custom/pdf/service/datafile/unitprice/2024/ken_c.pdf'
r = requests.get(pdf_url, allow_redirects=True)
open(pdf_path, 'wb').write(r.content)

# PDFファイルを開く
pdf_document = fitz.open(pdf_path)
for page_num in tqdm(range(0, len(pdf_document))):
    page = pdf_document.load_page(page_num)
    tables = page.find_tables()
    for table in tables:
        for row in table.extract():
            data.append(row)
    # DataFrameに変換
df = pd.DataFrame(data)
# 改行を削除
df = df.replace("\n", "", regex=True)
# 各ページに含まれていたインデックス行を1番上を除いて削除
df_tmp = df[:1]
contains = df[0].str.contains('帯名称')
df = df.drop(df[contains].index, inplace=True)
df = pd.concat([df_tmp, df])
# CSVファイルに保存
df.to_csv(csv_path, index=False, header=False)

print(f"PDF data has been successfully saved to {csv_path}")
```

## 積算資料

```python
import fitz
import pandas as pd
import requests
from tqdm import tqdm


pdf_url = 'https://www.zai-keicho.or.jp/wp-content/uploads/2024/05/denshiban-code1.pdf'
r = requests.get(pdf_url, allow_redirects=True)
open('local_sekisan.pdf', 'wb').write(r.content)

pdf_path = 'local_sekisan.pdf'
csv_path = 'sekisan-shiryo.csv'
data = []

# PDFから値を取り出し
pdf_document = fitz.open(pdf_path)
for page_num in tqdm(range(1, len(pdf_document))):
    page = pdf_document.load_page(page_num)
    tables = page.find_tables()
    for table in tables:
        for row in table.extract():
            data.append(row)

df = pd.DataFrame(data)
# 改行を取り除く
df = df.replace("\n", "", regex=True)
# 上の値を使って欠損値を埋める
df = df.fillna(method='ffill')
# 各ページに含まれていたインデックス行を1番上を除いて削除
df_tmp = df[:1]
contains = df[0].str.contains('分類２名称')
df.drop(df[contains].index, inplace=True)
df = pd.concat([df_tmp, df])

df.to_csv(csv_path, index=False, header=False)

```
DTSA 5001 データサイエンスへの確率論の応用

学習した内容を深めるために、アウトプットするのが一番良い手段です。もし他人の参考にもなれば、最高です。
そのため、こちらのコース[DTSA 5001 Probability Theory: Foundation for Data Science](https://www.colorado.edu/program/data-science/coursera/curriculum/dtsa5001)から重要なポイントを抜粋し、自分なりの解釈を加えてこちらに残しています。

# 全体概要

このコースでは、主に以下の六つを紹介しています。
- 記述統計と確率の公理
- 条件付き確率
- 離散確率変数
- 連続確率変数
- 同時分布と共分散
- 中心極限定理

# 記述統計と確率の公理

統計解析には、大きく分けて2つの種類があります。それは、記述統計と推測統計です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177240/d10fa5a1-324f-f30e-ce53-1c37d8a81207.png)

- 　「記述統計」とは、「データが持つ特徴を読み解くための手法」です。手元のデータから、「平均値」や「中央値」、「標準偏差」などの数値を算出することによって、そのデータが何を意味しているのかを読み解きます。
- 　「推測統計」とは、「一部のデータから、全体のデータの性質を推測するための手法」です。例えば、ある国の一つの畑の収穫高から国家全体の収穫高を予測したり、わずか1000人程度のアンケート調査から国民全体の傾向を考えたりします。

## 順列と組み合わせる

### 1. 順列 (Permutations)
順列とは、$n$個の異なる要素から$r$個の要素を取り出して並べる全ての異なる並べ方を指します。順列では要素の順序が重要です。例えば、文字A, B, Cから2つを選んで文字列を作成する場合、「AB」と「BA」は異なる順列と見なされます。

**公式**:
もし、$n$個の異なる要素から$r$個を選んで並べる場合、順列の数は以下の公式で計算できます:
$P(n, r) = \frac{n!}{(n-r)!} $
ここで、$ n! $ は$n$の階乗を示し、つまり $ n \times (n-1) \times \cdots \times 1 $ です。

```r
# Rで順列の関数が無いので、factorial(n)で計算
# 10個から三つを選んで順列であれば、P(10,3) = 10!/(10-3)!
factorial(10) / factorial(10 - 3) # 720

# prod は積を求める関数であり、 10:8 は10から8までの数の範囲を表します。
prod(10:8) # 720
```

### 2. 組み合わせ (Combinations)
組み合わせとは、$n$個の異なる要素から$r$個の要素を選び出す方法を指しますが、順列と異なるのは、組み合わせでは要素の順序を考慮しないことです。例えば、文字A, B, Cから2つを選んで組み合わせを作る場合、「AB」と「BA」は同じ組み合わせと見なされます。

**公式**:
n個の異なる要素からr個を選ぶ組み合わせの数は以下の公式で計算できます:
$ C(n, r) = \binom{n}{r} = \frac{n!}{r!(n-r)!} $
ここで、$ \binom{n}{r} $ は組み合わせ数（コンビネーション）を表し、二項係数とも呼ばれます。
```r
# Rで組み合わせの関数があり、choose(10,3)
choose(10,3) # 120

# あるいは
factorial(10) / (factorial(10 - 3)*factorial(3)) # 120
```
# 条件付き確率

## 条件確率

条件確率とは、ある事象が発生したという情報が与えられたときに、別の事象が発生する確率のことです。
数式で表すと、事象 $ A $ と $ B $ があり、事象 $ B $ の確率がゼロでない場合 $P(B) > 0 $、**事象 $ B$ が発生した条件下で事象 $ A$ が発生する条件確率**は以下の式で表されます：

$ P(A|B) = \frac{P(A \cap B)}{P(B)} $

ここで、 $ P(A \cap B) $ は事象 $ A $ と $ B $ が同時に発生する確率、 $ P(B) $ は事象 $ B $ が発生する確率です。条件確率は、特定の情報が与えられた状況で事象の確率を再評価するために使用されます。

```r
P_AB <- 0.1  # Probability of A and B
P_B <- 0.2   # Probability of B

# Bが発生した条件下で、Aが発生する確率
P_A_given_B <- P_AB / P_B
print(P_A_given_B) # 0.5
```

## ベイズの定理 (Bayesian Theorem)

ベイズの定理とは、ある事象が発生した条件の下で別の事象が発生する確率を計算するための数理的な定理です。これは、条件付き確率を用いて、観察データに基づいて事象の確率を更新する方法を提供します。

ベイズの定理の公式は次の通りです：

$ P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)} $

ここで、
- $ P(A|B) $ は、事象$ B $ が発生した条件下での事象 $ A $ の条件付き確率。
- $ P(B|A) $ は、事象$ A$が発生した条件下での事象 $ B $ の条件付き確率。
- $ P(A) $ は、事象$ A$の事前確率。
- $ P(B) $ は、事象$ B$の事前確率。

ベイズの定理は、特に統計学やデータサイエンスの分野で広く用いられ、予測モデルや推論の基盤となっています。

# 参考

https://qiita.com/DeepTama/items/85470a66972432e14224
アジャイル開発とは？

# はじめに
こんにちは！みなさんアジャイル開発についてご存知でしょうか？
今回はアジャイル開発とは何かについて掘り下げていきたいと思います。

# 対象読者
- アジャイル開発に興味がある方
- ソフトウェア開発の新しい方法論を学びたい方
- チームをより効率的に運営したいプロジェクトマネージャー

# 目次
1. アジャイル開発とは？
    - アジャイルマニフェストの基本
2. 最新トレンド
    - デジタルトランスフォーメーションとアジャイル
3. ベストプラクティス
    - 効果的なスクラムの実践方法
4. アジャイルツールの選び方
    - 最適なツール選定のポイント

# 1. アジャイル開発とは？
アジャイル開発の基本についておさらいしましょう。アジャイルマニフェストが掲げる4つの価値と12のプリンシプルは、成功するソフトウェア開発の核です。

## アジャイルマニフェストの基本
アジャイルマニフェストは、2001年に17人のソフトウェア開発者が提唱しました。4つの価値:
- **個人と対話**をプロセスとツールよりも重視する。
- **動くソフトウェア**を包括的なドキュメントより重視する。
- **顧客との協調**を契約交渉より重視する。
- **変化への対応**を計画に従うことより重視する。

これらの価値は、顧客の要求や市場の変化に柔軟に対応できることを目指しています。
# 2. 最新トレンド
技術の進歩とともに、アジャイル開発も進化しています。デジタルトランスフォーメーションの波に乗り、アジャイルは新しい領域に足を踏み入れています。

## デジタルトランスフォーメーションとアジャイル
デジタルトランスフォーメーション（DX）は、デジタル技術を活用してビジネスモデルや業務プロセスを革新することです。アジャイルはその迅速な適応力と顧客重視の考え方がDXにぴったりです。

:::note info
**DXにおけるアジャイルの導入事例**
バンク・オブ・アメリカは、アジャイル開発を導入して顧客向けのモバイルアプリの開発速度を大幅に向上させました。
:::

さらに、「DevOps」というキーワードも増えています。DevOpsは開発（Development）と運用（Operations）を統合した方法論で、アジャイルの価値観と非常に親和性があります。これにより、ソフトウェアのリリースサイクルが短縮され、品質が向上することが期待できます。

# 3. ベストプラクティス
アジャイル開発を効果的に実施するためには、ベストプラクティスを知ることが重要です。ここではスクラムを例に、いくつかのベストプラクティスを紹介します。

## 効果的なスクラムの実践方法
スクラムはアジャイル開発フレームワークのひとつです。以下のポイントに注目して、スクラムを効果的に運用してみましょう。

1. **スプリントの短縮**: 1〜2週間のスプリントが推奨されます。短いサイクルでスプリントを回すことにより、フィードバックサイクルが早くなり、迅速な改善が可能です。
2. **デイリースクラム（デイリースタンドアップ）**: 毎日15分間のミーティングで、チームメンバーが各自の進捗状況を共有し、問題点を速やかに解決する場を設けます。
3. **リトロスペクティブの活用**: スプリント終了後のリトロスペクティブ（振り返り会）では、何がうまくいったのか、何が改善できるのかをチーム全体で話し合います。これにより、次のスプリントでの改善点が明確になります。

:::note info
**Tips**: スクラムボードを使って、タスクの進捗状況を可視化することで、チーム全体のモチベーションが向上します。
:::

# 4. アジャイルツールの選び方
アジャイル開発を成功させるためには、適切なツールの選定が不可欠です。以下に、いくつかの選定ポイントを紹介します。

## 最適なツール選定のポイント
1. **チームの規模とニーズ**: 小さなチームと大規模なチームでは必要なツールが異なります。チームの規模やプロジェクトの複雑さに応じて最適なツールを選びましょう。
2. **機能の充実度**: プロジェクト管理、バグトラッキング、連携・コミュニケーション機能が豊富なツールを選びます。例えば、JIRAはプロジェクト管理に優れており、Slackはコミュニケーションを円滑にします。
3. **ユーザビリティ**: 使いやすさも重要です。複雑なツールはチームの生産性を下げる可能性があります。直感的に操作できるツールを選びましょう。

:::note info
**おすすめツール**:
- **JIRA**: プロジェクト管理の王道ツール。タスクの作成、進捗管理が容易です。
- **Trello**: 簡単なカンバンボードとして利用可能。小規模なプロジェクトに最適。
- **Slack**: コミュニケーションツールの定番。プラグインで他のツールとも連携可能。
:::

# まとめ
アジャイル開発は、柔軟で迅速な適応が求められる現代のソフトウェア開発において非常に価値があります。アジャイルマニフェストの基本から最新のトレンド、効果的な実践方法、そして適切なツールの選び方まで、一通りのポイントを押さえておけば、あなたのチームもきっと成功に近づくでしょう。ぜひ試してみてください！

# 参考文献

https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0249311

https://www.mdpi.com/2674-113X/1/3/12

https://link.springer.com/book/10.1007/978-3-642-12575-1

https://link.springer.com/article/10.1007/s13198-019-00840-7
「Composeの基本レイアウト」のメモ#5 ~Favorite collection カードの実装~ 

### [6. Favorite collection カード - マテリアル サーフェス](https://developer.android.com/codelabs/jetpack-compose-layouts?hl=ja#5)
+  カスタマイズ性の高いカードを作成するので、Surface コンポーザブルを使用して作成する
+  画像と文字列を横並びで設定するので、以下の構成となる
+  Surface（)
    +  Row()
        +  Image()
        +  Text()

#### 最小構成
```Kotlin
@Composable
fun FavoriteCollectionCard(
    modifier: Modifier = Modifier
){
    Row(
        modifier
    ) {
        Image(
            painter = painterResource(R.drawable.),
            contentDescription = null
        )
        Text(
            text = stringResource(R.string)
        )
    }
}
```

#### Imageコンポーザブルの微調整

[Imageコンポーザブルの調整パラメータ](https://qiita.com/tiger98/items/ad8b0b9c6fa4c940b648#image%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%82%B6%E3%83%96%E3%83%AB%E3%81%AE%E8%AA%BF%E6%95%B4%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF)と同様に、`contentScale`と`Modifier.size`で画像を調整する。

#### Rowコンポーザブルの微調整
+ [Columnコンポーザブルの調整パラメータ](https://qiita.com/tiger98/items/ad8b0b9c6fa4c940b648#column%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%82%B6%E3%83%96%E3%83%AB%E3%81%AE%E8%AA%BF%E6%95%B4%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF)と同様に、縦方向の調整を`verticalAlignment`で調整する
+ 横幅を255.dpにする
    + modifier = Modifier.width(255.dp)


#### Textコンポーザブルの微調整
+ 左右にpaddhingを追加して位置を調整する
    + modifier = Modifier.padding(horizontal = 16.dp)
Java 関数型インタフェースの理解

# はじめに
ラムダ式、メソッド参照を用いることで簡潔なコード記述を可能になり、直感的なプログラミングが可能になります。
[関数型インタフェース](https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/package-summary.html)

# コード比較
今回は関数型インタフェースSupplierを用いた”Hello world"をコンソール出力するサンプルコードを比較する

### 従来のコード
抽象メソッドについては、オーバーライドによって中身の実装を行います。
```java
@FunctionalInterface
interface Greeting {
    String getGreeting();
}

public class App {
    public static void main(String[] args) {
        Greeting greeting = new Greeting() {
            @Override
            public String getGreeting() {
                return "Hello World!";
            }
        };

        System.out.println(greeting.getGreeting());
    }
}
```

### lambdaを用いたコード
**１つの抽象メソッドを持つインタフェース**ではラムダ式を利用可能となります。
ラムダ式では中身の実装については、下記のように簡潔になります。
```java
@FunctionalInterface
interface Greeting {
    String getGreeting();
}

public class App {
    public static void main(String[] args) {
        Greeting greeting = () -> "Hello World!";
        System.out.println(greeting.getGreeting());
    }
}
```

### まとめ
ラムダ式は、簡潔なコード記述を可能にし、直感的なコード記述が可能になります。
毎週更新：AIニュースまとめの記録と振り返り　そしてGPTsで検索へ

### いきさつ
2021年8月から毎週、その週にあったAI関連ニュースをnoteにまとめて配信しています。
もうすぐ３年になるのですが現在142本書いてました。
毎週書いていると、このニュースに関連することが前にもあったなーと思ったとき、
自分で検索して時間がかかっていました。


### そこでGPTsつくりました。
https://chatgpt.com/g/g-7kAz9thS9-takayuki-ioki-s-note-ainews-explorer

キーワードを入れると、そのニュースを乗せた週のリンクを探してくれます。

### こんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587072/e333b468-eb7f-d320-3eea-f8668e502fec.png)

### 最後に
過去のAIニュースを複数探したいときに活用してください。
「Composeの基本レイアウト」のメモ#4 ~AlignYourBodyの実装~ 

### デザインの詳細
+ 画像の高さは 88 dp にする
+ テキストのベースラインと画像の間隔は 24 dp にする
+ ベースラインと要素の底部の間隔は 8 dp にする
+ テキストは bodyMedium のタイポグラフィスタイルにする

#### 最小構成
+ `AlignYourBodyElement()`
    + modifier
    + Column()
        + modifier
        + Image()
        + Text()
```Kotlin
@Composable
fun AlignYourBodyElement(
    modifier: Modifier = Modifier
){
    Column(
        modifier = modifier
    ) {
       Image(
           painter = painterResource(R.drawable.),
           contentDescription = null
       )
       Text(text = stringResource(R.string.))
    }
}

```
#### Imageコンポーザブルの調整パラメータ
+ Imageコンポーザブル
    + contentScale
        + ContentScale.Cropで切り抜きの指定
            + modifierでのサイズ指定をもとに切り抜く
            + → contentScaleとmodifierはセットで機能する
    + modifier
        + 画像サイズの指定
            + Modifier.size(88.dp)　
        + 画像形状の指定
            + .clip(CircleShape)
            + 円形を指定

#### Columnコンポーザブルの調整パラメータ
+ ColumnでラップしているUI要素を水平方向に中央揃えで配置
    + horizontalAlignment = Alignment.CenterHorizontally

#### Textコンポーザブルの調整パラメータ
+ BaseLineからのpadding調整
    + modifier = Modifier.paddingFromBaseline(top = 24.dp, bottom = 8.dp)
+ 文字のFont設定
    + style = MaterialTheme.typography.bodyMedium