OmniAICreator/Qiita-1.07M huggingface dataset:
2024年に読んでよかった技術書3選 ~シェフの気まぐれUdemyコースを添えて~

早いものでもう年末。ということで今年読んでよかった技術書を紹介します！
紹介するまでもなく名著なのですが、もし興味を持っていてまだ読んでいない方がいればこの機会にぜひ、手に取っていただければと思います。

 ## 1. 失敗から学ぶRDBの正しい歩き方
 ![失敗から学ぶRDBの正しい歩き方](https://m.media-amazon.com/images/I/81z7uX1cs5L._SY466_.jpg "失敗から学ぶRDBの正しい歩き方")

 https://amzn.asia/d/a5PpAn8

 自分が過去に遭遇したアンチパターン等も含まれていて、読んでいて胸が苦しくなりました。
 データベースは変更を加えることが難しいので設計には気を付けたいです。
 

 ## 2. ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本
 ![ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本](https://m.media-amazon.com/images/I/71fHxiaAFvL._SY466_.jpg "ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本")

 https://amzn.asia/d/23tVNTV

ドメイン駆動設計（DDD）の基本を学べる初心者(概念)向けのガイドブックです。

DDDの概念を理解していてもそれをどうコードに落とし込むかに悩む方も多いと思いますが、この書籍ではコードを見ながらDDDの概念を学べるためより理解が深まり、実際のプロジェクトに活かせるようになると思います。

最近は[ドメイン駆動設計をはじめよう](https://amzn.asia/d/4K1xY0Y)も気になっています。

## 3. Good Code, Bad Code ～持続可能な開発のためのソフトウェアエンジニア的思考
 ![Good Code, Bad Code ～持続可能な開発のためのソフトウェアエンジニア的思考](https://m.media-amazon.com/images/I/81VS3ZONcSL._SY466_.jpg "Good Code, Bad Code ～持続可能な開発のためのソフトウェアエンジニア的思考")
 
 https://amzn.asia/d/9Rfv8dz

 Googleでテックリードを務める著者が、堅牢で信頼性が⾼く、保守しやすく、チームメンバーが理解や適応しやすいコードを作成するための概念と実用的な手法を解説しています。

 コードレビューをする際この本を参照してレビューすることも多く、個人的に経験の浅い方にはリーダブルコードよりこの本をおすすめしたいです。

## 番外編.NestJS + Microservicios: Aplicaciones escalables y modulares
  https://www.udemy.com/share/10aQ2O3@E-DYxQQKRouJeqK7KftIvnzgYNLPmSujokZB1z474J6qqggUXQIUmeZOVuDnAlxl5A==/

最後は本ではなくUdemyなのですがTypeScriptのバックエンドフレームワークであるNestJSを用いたマイクロサービス化について学べるコースです。

スペイン語ですがコードを読めば伝えたいことは明白なのでスペイン語ができなくても大丈夫です。~~字幕付けてます。~~

## 最後に
いかがだったでしょうか。
これらの書籍を通して得た知識は日々の開発にとても役立っており、著者の方々には海が裂けるほど感謝しています。
来年も新しい知識を得て、より良いプロダクトを生み出していきたいです。

今回紹介した書籍やUdemy講座の購入には弊社の書籍購入支援制度を活用させていただきました。
バリューページではエンジニア・デザイナーを募集中です！成長を重視する環境で、一緒に学び、挑戦し続けたい方はぜひ応募いただければと思います！

https://vpage.co.jp/
Reactを勉強し直す 〜 v16.5~16.13 〜

# はじめに
引き続きReact16から再勉強していきます。

前回はこちら。

https://qiita.com/mattsu_mocha/items/0e08566eaefd47782bfa

# React 16.5~16.13
以下にReact 16.5~16.13で追加された機能について一部抜粋しながらまとめていく。

※ 16.10~16.13はbugfixが多かったため記載していない。

## React Profiler
React Developer Toolsの機能の1つで、Reactアプリケーションのパフォーマンスのボトルネックを特定することができる。これによって各コンポーネントのレンダリング頻度等のパフォーマンスを計測が可能となる。

これを使うにはChromeの拡張機能を入れる必要がある。

https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ja

また、のちにプログラム的な方法として`<React.Profiler>`が登場した。

```React
import React, { Profiler } from 'react';

const onRenderCallback = (
  id, // プロファイラーツリーのID
  phase, // "mount" または "update"
  actualDuration, // レンダリングにかかった時間
  baseDuration, // メモ化なしでかかる時間
  startTime, // レンダリングの開始時間
  commitTime, // レンダリングの終了時間
  interactions // このレンダリングに関連するインタラクション
) => {
  console.log({ id, phase, actualDuration, baseDuration, startTime, commitTime, interactions });
}

const App = () => {
  return (
    <Profiler id="App" onRender={onRenderCallback}>
      <MyComponent />
    </Profiler>
  );
}

const MyComponent = () => {
  return <div>Hello, world!</div>;
}
```

## React.memo
クラスコンポーネントの場合はpropsの値が同じ場合、[PureComponent](https://legacy.reactjs.org/docs/react-api.html#reactpurecomponent)や[shouldComponentUpdate](https://legacy.reactjs.org/docs/react-component.html#shouldcomponentupdate)を使うことで再レンダリングを防いでくれる。

関数コンポーネントはReact.memoを使うことで同じことができるようになった。

```React
const MyComponent = React.memo((props) => {
  /* only rerenders if props change */
});
```

## React.lazy
コンポーネントを遅延読み込みする時に使う。これによって必要なときにコンポーネントを読み込め、初期ロード時間を短縮できる。

さらにSuspenseを使うとSuspenseの子要素がローディングされるまでの間、fallbackに指定した要素を表示する。

```React
import React, {lazy, Suspense} from 'react';
// 初期ロードでは読み込まない
const OtherComponent = lazy(() => import('./OtherComponent'));

const MyComponent = () => {
  return (
    // OtherComponentをローディングしている間、fallbackに指定した要素を表示する
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />
    </Suspense>
  );
}
```

## React Hooks
React v16.8で安定版がリリース :confetti_ball: 

これまでは状態管理がクラスコンポーネントでしかできなかったが、React Hooksの登場により、関数コンポーネントでも同じことができるようになった。代表的なHooksとして、`useState`、`useEffect`等がある。

```React: useState
import React, { useState } from 'react';

const MyComponent = () => {
  const [name, setName] = useState('Edward');

  const handleClick = () => {
    // 実行されるとTaylorにnameの状態が変わる
    setName('Taylor');
  };

  return (
    <button onClick={handleClick}>押したら名前が変わる</button>
  );
};
```

```React: useEffect
import { useEffect } from 'react';
import { createConnection } from './chat.js';

const ChatRoom = ({ roomId }) => {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  // 初回表示時および serverUrl または roomId が更新されたときにチャットルームのコネクションを張る
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
    return () => {
      connection.disconnect();
    };
  }, [serverUrl, roomId]);
  // ...
}
```

詳しくはこちら。

https://ja.react.dev/reference/react/hooks

# 参考

https://ja.legacy.reactjs.org/blog/2017/09/26/react-v16.5.html
getElementByIdとquerySelectorの要素探索方法

## 要素の取得
要素オブジェクトの参照を取得する方法として、`getElementById`や`querySelector`というDOM APIがあります。
この2つのAPIはどちらも`id`を指定して要素を取得できますが、目的の要素の探索方法が異なります。

`id`というのはドキュメント内で一意である必要があります。
`querySelector`は`id`の他にも様々な方法で取得する要素の条件を指定できるため、`id`のみの指定を受け付ける`getElementById`とは探索アルゴリズムが異なっているわけですね。

## querySelector
`querySelector()`はCSS セレクタの記法を用いて要素を取得する関数です。
ドキュメント内の要素でセレクタに一致する最初のものを返します。
`document`オブジェクトのほか、要素オブジェクトにも存在するAPIで、要素オブジェクトにある`querySelector`はその要素内のみを探索します。

`id`を指定するときには、`querySelector(#foo)`のように`#`を使って指定します。
`getElementById`の場合には`#`の指定は不要ですが、`querySelector`では`#`をつけないと`id`ではなくタグ名で探索されてしまいます。

### 探索方法
`querySelector()`はドキュメント内を上から順に探索していきます。
上から順に1つずつ探索し、セレクタに一致した要素が返されます。
これは線形探索であり、計算量はO(N) となります。

## getElementById
`getElementById()`は引数に渡した`id`をもつ要素オブジェクトを取得する関数です。
`document`オブジェクトから生えているAPIであり、要素オブジェクトには生えていない点が`querySelector`とは異なっています。

`id`が一意に設定されていなかった場合には、指定した`id`をもつドキュメント内の最初の要素が返されます。
また、指定した`id`をもつ要素が見つからなかった場合には`null`が返されます。

### 探索方法
`getElementById()`によって要素を探索するとき、（ブラウザの実装によりますが、）ハッシュマップのようなデータ構造を使用して探索を行う場合、計算量はO(1)となります。
`id`と対応する要素を紐づけているため、高速に取得することができるわけです。

`getElementById`は`querySelector`と比べて高速です。

## 計測
10万個ほどの要素をもつドキュメント内の初めの方にある要素と終わりの方にある要素を取得するのにかかる時間を以下のような`html`で計測してみます（計測は１度のみ行っています）。

```html
<html>
<body>
    <div id="first">first target</div>
    {... 約10万個の<div>要素}
    <div id="target">last target</div> 
</body>
<script>
console.time('querySelector')
const target = document.querySelector('#target')
console.timeEnd('querySelector')

console.time('getElementById')
const targetElementById = document.getElementById('#target')
console.timeEnd('getElementById')

console.time('querySelectorFirst')
const targetFirst = document.querySelector('#first')
console.timeEnd('querySelectorFirst')

console.time('getElementByIdFirst')
const targetElementByIdFirst = document.getElementById('#first')
console.timeEnd('getElementByIdFirst')

</script>
</html>
```

ドキュメントの初めの方にある要素`<div id="first">first target</div>`を取得するまでにかかった時間は以下の通りです。

```
querySelectorFirst: 0.001953125 ms
getElementByIdFirst: 0.0009765625 ms
```
ドキュメントの初めの方にある要素を取得する場合には、`querySelector()`は`getElementById()`の約２倍の時間がかかっています。


一方、ドキュメントの最後の方にある要素`<div id="target">last target</div> `を取得するまでにかかった時間は以下の通りです。
```
querySelector: 0.069091796875 ms
getElementById: 0.003173828125 ms
```
10万個の要素を上から探索している`querySelector()`は、`getElementById()`の２0倍以上の時間がかかってしまっています。
要素数が大きいほど、両者の処理時間の差が開いていくことが確認できます。

### 計測環境
以下の環境で計測を行っています。
```
OS	macOS バージョン15.1.1
Google Chrome	131.0.6778.109 (Official Build) （arm64） 
JavaScript	V8 13.1.201.15
```

## さいごに
`document.querySelector()`と`document.getElementById()`とでは、`getElementById()`の方が高速に処理できます。
`id`を指定して要素を取得する際には、パフォーマンスの観点では`getElementById()`に軍配が上がります。

https://developer.mozilla.org/ja/docs/Web/API/Document/getElementById

https://developer.mozilla.org/ja/docs/Web/API/Document/querySelector
iOS Widget データ共有の基本

iOS App と Widget 間でデータを共有する場合にいくつか注意が必要です。

まず、 App と Widget では Bunlde Identifier が異なり、 OS 側から両者は区別されます。 Apple は、こういった状況でデータを共有する仕組みとして App Groups を用意しています。

https://developer.apple.com/documentation/xcode/configuring-app-groups

以下は、アプリから入力した値を Widget で表示するサンプルアプリです。このサンプルアプリの解説を通して App と Widget でのデータ共有について説明します。

https://github.com/ykws/HomeMemo

:::note warn
もしクローンして手元の環境で試される場合は、以下の変更が必要です。
- Team
- Bundle Indentifier
- App Groups
:::

## App Groups の指定
App と Widget それぞれの Signing & Capabilities で同じ App Groups を指定しています。

![Screenshot 2024-12-07 at 14.18.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31787/c8f079a0-a02b-7fac-63f1-7f5998005e2d.png)

コード上では、 [HomeMemo.entitlements](https://github.com/ykws/HomeMemo/blob/4ec9c7533b12205ee86342fe708f7076c48030c0/HomeMemo/HomeMemo.entitlements#L7) と [HomeMemoWidgetExtension.entitlements](https://github.com/ykws/HomeMemo/blob/4ec9c7533b12205ee86342fe708f7076c48030c0/HomeMemoWidget/HomeMemoWidgetExtension.entitlements#L7) の `<key>com.apple.security.application-groups</key>` の部分で確認できます。

これで App と Widget でデータ共有する準備が整いました。

## UserDefaults への保存

`UserDefaults(suiteName)` で App Groups を指定して保存します。

https://developer.apple.com/documentation/foundation/userdefaults/1409957-init

```swift
UserDefaults(suiteName: appGroupId)?.set(name, forKey: "name")
```

https://github.com/ykws/HomeMemo/blob/4ec9c7533b12205ee86342fe708f7076c48030c0/HomeMemo/ContentView.swift#L31

この時、 App Groups には Capabilities に設定されているものと同じ値を指定します。違うものを指定すると、 Widget から読み込みできません。サンプルアプリでは、 `appGroupId = "group.io.github.ykws.example.HomeMemo"` としています。

## UserDefaults からの読み込み

保存した時と同じ App Groups を指定して読み込みます。

```swift
UserDefaults(suiteName: appGroupId)?.string(forKey: "name") ?? ""
```

https://github.com/ykws/HomeMemo/blob/4ec9c7533b12205ee86342fe708f7076c48030c0/HomeMemoWidget/HomeMemoWidget.swift#L45

## Widget への反映

Widget に対してすぐに反映したい場合は再読み込みを明示します。

```swift
WidgetCenter.shared.reloadAllTimelines()
```

https://developer.apple.com/documentation/widgetkit/widgetcenter/reloadalltimelines()/

Demo イメージはサンプルアプリの README に添付しているのでそちらから確認できます。
【Goで学ぶコンピューターサイエンス】スタックとキュー

## スタック (Stack)
スタックは **LIFO (Last In First Out)**、つまり「最後に入れたものが最初に取り出される」データ構造です。
お皿を積み重ねて、一番上に置いた皿を最初に取り出すようなイメージです。

### 使用例
- 関数呼び出しの管理 (コールスタック)
- Undo機能の実装

### 主な操作
- **Push**
    - データをスタックの一番上に追加する
- **Pop**
    - データをスタックの一番上から取得する

### Goサンプルコード

```go
package main

import "fmt"

// スタックの定義
type Stack struct {
	data []int
}

// データを追加
func (s *Stack) Push(value int) {
	s.data = append(s.data, value)
}

// データを取得
func (s *Stack) Pop() (int, bool) {
	if len(s.data) == 0 {
		// 空の場合
		return 0, false
	}
	value := s.data[len(s.data)-1]
	s.data = s.data[:len(s.data)-1]
	return value, true
}

func main() {
	stack := &Stack{}

	// データを追加
	stack.Push(10)
	stack.Push(20)
	stack.Push(30)

	// データを取得
	value, ok := stack.Pop()
	fmt.Println("Pop:", value, "result:", ok)
	value, ok = stack.Pop()
	fmt.Println("Pop:", value, "result:", ok)
	value, ok = stack.Pop()
	fmt.Println("Pop:", value, "result:", ok)
	value, ok = stack.Pop()
	fmt.Println("Pop:", value, "result:", ok)
}
```

```
Pop: 30 result: true
Pop: 20 result: true
Pop: 10 result: true
Pop: 0 result: false
```

## キュー (Queue)

キューは **FIFO (First In First Out)**、つまり「最初に入れたものが最初に取り出される」データ構造です。
飲食店の待ち行列のようなもので、先頭の人から順番に呼ばれるイメージです。

### 使用例
- タスクスケジューリング
- メッセージキュー

### 主な操作
- **エンキュー**
    - データをキューの末尾に追加する
- **デキュー**
    - データをキューの先頭から取得する

### Goサンプルコード

```go
package main

import "fmt"

// キューの定義
type Queue struct {
	data []int
}

// データを追加
func (q *Queue) Enqueue(value int) {
	q.data = append(q.data, value)
}

// データを取得
func (q *Queue) Dequeue() (int, bool) {
	if len(q.data) == 0 {
        // 空の場合
		return 0, false
	}
	value := q.data[0]
	q.data = q.data[1:]
	return value, true
}

func main() {
	queue := &Queue{}

	// データを追加
	queue.Enqueue(10)
	queue.Enqueue(20)
	queue.Enqueue(30)

	// データを取得
	fmt.Println("Dequeue:", queue.Dequeue())
	fmt.Println("Dequeue:", queue.Dequeue())
	fmt.Println("Dequeue:", queue.Dequeue())
	fmt.Println("Dequeue:", queue.Dequeue())
}
```

```
Dequeue: 10 result: true
Dequeue: 20 result: true
Dequeue: 30 result: true
Dequeue: 0 result: false
```
マインドマップを使いこなす

## マインドマップとは

トニー・ブザン氏が提唱した、思考を可視化する手法です。
成果物であるマップを、図ではなく絵であると認識させることによって、
右脳の働きを活発にし、想像を膨らませるというものです。

人間の脳は、飛躍した発想はできないとされており、
例えば、日本というセントラルイメージがあるとして、
都道府県、地域、枝番というふうに発想がつながりますが、日本→枝番という、いきなりの発想は
できないといわれています。
ところが、ソフトウェアテストでは、この枝番、が出てくることが大事だったりします。
こういう発見を得るために便利なのが、マインドマップです。

海外の講師を迎えたチュートリアルのクラスで、講師からの質問として、
「マインドマップを知っているか？」というものがありました。
その時挙手していたのが、チュートリアルに参加されている方の
半数ぐらいでしたので、マインドマップは、QAクラスタでは国内外を問わず、
ポピュラーと言えるでしょう。


## なぜマインドマップがいいの？
### 右脳を活性化させる
脳は、図は左脳的発想でみるものですが、図は右脳を使うので、思いつかなかったことを
思いついてつなげるには、右脳を刺激するのが有効、という説から、
できるだけ絵に近い書き方が
推奨されています。

そうはいっても、仕事で使うには手書きだと時間がかかってしまうので、
実際にはツールを使うことになりますが、こういう経緯があるのを知っておくと、
気分を変えて手書きにする、という選択肢もでてくるかもしれません。


### 気づきを得る
枝をつなげていくことで、いきなりリスト化したときには思いつかなかったものに
気づきやすくなります。

また、書いたマップは、書き始めてから、30分ぐらいで一度アイデアを
出しきるといわれています。書ききったら、そこから30分置いたり、
一晩置くと、また新しい発見があることもあります。

マインドマップのこの特性を利用して、こんな使いかもあります。
- 赤ちゃんの言いたいことを探る
- 将来なりたいもの・作りたいものの実現のために必要なものを探る
- 作業のクリティカルパスを出す 

## どういうときに使うの？

ソフトウェアテストにおいては、
- 機能概要の整理
- ページオブジェクトの仕様の整理
- エンティティの関連
- テスト観点の洗い出し
などなど、多様な使い方が可能です。


## 書き方のコツ
マップを、脳に、絵と認識させるために、以下のテクニックがあります。

- カラフルに
- 線を使わない
- セントラルイメージは派手に書く
- 絵として認識することで、右脳を働かせ、想像力を広げる
- 太い枝から細い枝へ
- 線は、最初が太く、先に細く、S字を描くように蛇行させる
- 枝は、しっかり塗りつぶす
- 文字は、単語が基本
- 文字は、線に沿って書く



## 機能を整理して、テストのポイントを見極める

![ブラウザ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/1b2aa758-4bb9-1f1b-726f-9aaf3ec32685.png)

これは、その昔、ブラウザの機能を整理して、ユーザーの操作を想定するために起こした
ブラウザの機能をツリーにしたマインドマップです。

ここから、処理の分岐となる要素を洗い出し、テンプレート化しています。
これを、ブラウザ特性のテストとして、コンパチビリティテストに使っています。


### さらに活用するには
「ぐるぐるマインドマップ」と呼ばれる、マインドマップをリレー形式の多人数で
繋いでいく、というやり方があります。これだと、ほかの方が気づいたことから
発想を広げられるので、実例マッピングなどのように、仕様のアイデア出しなどに
良いと思います。

また、マインドマップ講師の公式資格などもあります。

## マインドマップのツール
#### Xmind
定番。無料でも使えますが、毎年ライセンスが変わっています。
#### Miro
Miroにも、マインドマップの機能があります。これだと、チーム全員で使えますね。

## 最後に
本を一つ、紹介させていただきます。
ソフトウェアテストでマインドマップを使うには、この本が有名でしょう。

[「［改訂新版］マインドマップから始めるソフトウェアテスト 」]("https://www.amazon.co.jp/%EF%BC%BB%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88%EF%BC%BD%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%89%E3%83%9E%E3%83%83%E3%83%97%E3%81%8B%E3%82%89%E5%A7%8B%E3%82%81%E3%82%8B%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88-%E6%B1%A0%E7%94%B0-%E6%9A%81-ebook/dp/B07QBNQ8T2/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=39BNI4QVV53Y1&dib=eyJ2IjoiMSJ9.hAkYr3HplzDwhjdt4LB1Ff5ayYiy836LraM1irZAzoLTXk2DVjNZf0SCWMhg4n8Xm45tnTSWMEROoo0jJCxIjztDC-KMFcmvLTTwBXRMl3xrUPc3KcMN0tN4LJUP1mxuCKtofF6kpoC5nk8NsoWsQgS4M6z-XpxpeO7R58p9Ty_XY6RoCYPpEaAW2QUSpxTQ.9hBekakt2Gc_L5VtXL271D5HYQnaSnObSgdQ5nMSWWA&dib_tag=se&keywords=%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%89%E3%83%9E%E3%83%83%E3%83%97+%E6%9C%AC+%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88&qid=1733553079&sprefix=%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%89%E3%83%9E%E3%83%83%E3%83%97+%E6%9C%AC+%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%86%E3%82%B9%E3%83%88%2Caps%2C152&sr=8-1")
[rembg] AIで背景を消してみよう [Mac向け]

## 環境
OS: Sonoma
pythonのバージョン: Python 3.10.6
ターミナルエミュレータ: iTerm2
rembg: 2.0.60

## pipx
pipx をインストール
```
brew install pipx
```
pipx のパスをシェルに追加する
成功文がちょっとかわいいゾ

```
pipx ensurepath
```
![スクリーンショット 2024-12-07 15.36.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/972167ba-f6a2-4d2c-bc62-d80c6b9e05aa.png)

変更を反映
```
source ~/.zshrc
```
## rembgをインストール
```
pipx install rembg
```
バージョン確認
```
rembg --version
```
以下のようにバージョンが表示されればOK
```
rembg, version 2.0.60
```

使用できるコマンドを確認
```
rembg --help
```

```
Options:
  --version  Show the version and exit.
  --help     Show this message and exit.

Commands:
  b  for a byte stream as input
  d  download all models
  i  for a file as input
  p  for a folder as input
  s  for a http server
```

## 実行
```
rembg i input.webp output.png
```
精度が微妙だ！！

![input.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/4064f192-0877-d5b9-13dc-779736088e49.png)
![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/643de179-61df-748f-f1fb-665f56da847e.png)


諦めるのはまだ早い、デフォルトではu2netというモデルが使用されているんだが、
人物に特化したu2net_human_segなど、他のモデルを使うことができるぞ！

まずは使用可能なモデル一覧を確認しよう!
```
rembg d
```
いろいろダウンロードがはじまる
![スクリーンショット 2024-12-07 16.12.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/cb6483eb-9ac9-660b-01fd-fd202e1dca14.png)


終わったら別のモデルも試してみよう！
```
rembg -m u2net_human_seg -i input.webp -o output.png
```
ArgoCDのsyncの違いについてまとめてみる

# はじめに
ArgoCDには4種類のSyncがあります。その違いがなんだか自分はあんまりわからず、とりあえず普通にsyncしたり、Out Of Syncの時に無理やりforce syncしたりみたいな感じで雑な使い方をしていました。(危ないことをしてしまっていた…)
このSyncの違いについて改めてまとめたのでその内容をこの記事で紹介していきます。

# Syncについて
## ArgoCDにおけるSyncとは
ArgoCDでSyncとはマニフェストファイルの変更を検知し、アプリケーション同期を行うことを意味します。マニフェストファイルにsyncPolicyを設定することで、自動でイメージを追跡することもできデプロイを行うことができ便利です。

基本的なSyncの動作フローを整理するとこのようになります。
1. マニフェストの読み込み
1. クラスタの現在の状態を確認
1. 差分の検出
1. バリデーションの実行
1. 変更の適用

ArgoCDにはこの通常のSyncとは少し違ったSyncが四つ用意されています。それぞれについて紹介していきます。
![スクリーンショット 2024-12-07 午後4.09.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546781/dabafc25-a371-dfc4-b1b8-8b4d50a3720d.png)


## Prune Sync
Prune Syncは追跡先のマニフェストから削除されたリソースをクラスタからも削除するというものです。
基本的にはこれらのリソースは誤って削除されないようにデフォルトではオフにされています。環境のクリーンアップだったり大規模リファクタリング時などのユースケースが考えられます。

## Dry Run Sync
このSyncでは実際のリソースの変更は行わず、変更内容をシミュレーションするだけのものです。どのリソースが作成、更新、削除されるかを事前に確認可能であり、本番環境への大規模な変更前に確認用として使用することができます。

## Apply Only Sync
このSyncはOut of Syncステータスのリソースのみを同期し、すでに同期されているリソースには変更を行いません。特定のコンポーネントの更新など部分的な変更を適応したい場合におすすめです。

## Force Sync
これは最強のSyncで、通常の検証プロセスをバイパスし、リソースの状態に関係なく強制的に同期を行います。
通常ArgoCDはリソースのヘルスチェックや依存関係、整合性などを検証するのですが、Force Syncではこれを無視します。
そのため、このSyncはバリデーションエラー等を無視する必要があるくらい緊急の時に使うのが良いのだと思います。

# まとめ
ここまで
最後にざっくりのSyncのイメージについて軽く共有してこの記事を締めたいと思います。皆さんは自分のように雑な使い方をしないようぜひこのイメージだけでも覚えていただけるとありがたいです。

- 普段の開発
    - 普通のSync
- 検証用
    - Dry Run Sync
- メンテナンス用
    - Prune Sync
- 部分更新用
    - Apply Only Sync
- 緊急時用
    - Force Sync
OpenStreetMapとの衝撃的な出逢いを思い返す

2015年4月、ネパールで大地震がおきた
![IMG_7139.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397581/83daa847-ba41-a292-e213-d0c0dff7ca33.jpeg)

## 異国でもそこにいるのは同じ人間
当時、私は大学に入学したばかり
慣れない大学生活に戸惑いながらも、自分で受ける授業を選択できるということに大きな喜びを感じていた。

「**私はなんて恵まれてるんだろう**」
大学に通わなかった/通えなかった友達を横目に少しの罪悪感と、18歳で就職を選べなかった自分の未熟さに不甲斐ない気持ちも確かにあった。

そんな時、ネパールで大地震がおきた。
私は3.11のことを思い出していた。14歳だった私は、当たり前に何もできなかった。

現地で人の命を救うこともできないし、ましてやお金がないので寄付すらもできない。
そもそも寄付にどのくらいの価値があるかも全くわからなかった。

しかし私はもう18歳で大学生になった。
中学生の時より少し大人になったのだ。

3.11の時は海外からたくさんの寄付や物資を日本はいただいた。さらに物だけではなく、**たくさんの祈りや人命救助への願い**をもらっていたことを私は知っていた。

それは15歳でNZに行った時、近所の外国の人と会話している時、あとはメディアを通しても知ることができた。

## 次は私たちがお返しする番だ
そう意気込んでみたのはいいが、18歳でお金も知識も人脈も何もない私に何ができる？

そんな葛藤を抱きながら学内ホームページをぼーっと見ていた時、転機は訪れた。

「**誰でもできる地図づくりを通してネパールを支援しませんか？**」
正確なタイトルは覚えていないが、こんな感じのメッセージが掲載されていた。

私は半信半疑な思いで、その地図づくりを教えてくれるという教授の呼びかけに応じた。

そこには教授にしては比較的若そうな人と、さらにその隣には大学生か？ってぐらい若そうな２人が前に座っていた。

呼びかけに応じた数人の学生達は自分のパソコンを持ってその２人を見ていた。

ちなみに私は数週間前に、ローンを組んで買った初めてのパソコン、MacBookを使う場面が来た！と内心ワクワクだった。

この時に出会った教授が、のちに私の恩師となる古橋先生だった。（隣にいた大学生はたむけんさんでした）

古橋先生は淡々と**OpenStreetMap**の編集の仕方をその場でレクチャーしていた。

本当に淡々と説明していたのだが、CrisisMappingという活動の目的を話す時それまで関わってきた先生達とはどこか違う、**自分の意思**が声にのっかっていた気がした。 

それは1時間弱の出来事で、まだなんだかよくわかっていなかったけれど
「お金がなくても、**時間とパソコンさえあれば国境を越えて人の役に立つことができる**。私にもやれることがある。」と、初めて身を持って体験したわけである。

## Crisis Mappingという活動
そもそも聞き馴染みがない読者に向けて、OpenStreetMapの解説からしよう。

世の中にはたくさんの地図があるが、その中でもOpenStreetMap(略して"OSM")は特別な地図だ。

どこが特別なのかというと主に次の2点
・誰でも無料で利用できるように公開されている
・世界中の有志作業者(マッパー)が地図を編集/作成している

※なおOSMの地図データはマッパーが追加したもの以外にも、政府や企業から提供されているデータも含まれている。

それゆえにOSMはしばしば、**地図のWikipedia**なんて表現をされたりもする。

Crisis Mappingの意味は
「自然災害等の危機的状況下で、その現場の状況がわかる地図を作り、世の中に発信することを目指す。」ということだが
災害発生時、私達はこのOSM上に地物データを描いている。

ここでちょこっと私たちの活動紹介
先ほど登場した古橋先生が作った「[NPO法人クライシスマッパーズ・ジャパン](http://crisismappers.jp)」という団体がある。

ここでは災害発生時、迅速に空撮画像を撮りマッパーに展開する災害ドローン救助隊「[DRONE BIRD](https://dronebird.org)」と言った取り組みもしている。

## 志のある卒業生の集まる場を作る
私は約２年前から先生が育てた学生のうち、志ある卒業生の集まる場を作ろうとしている。

私の身近にいた信頼できる２人を誘い、今は３人で活動中。これから少しずつ仲間を増やしていく予定だ。

地図づくりの活動は孤独だ。だからこそ仲間を作り、お互いに刺激し合う関係が必要だと考えた。
そして我々若い世代が自発的に動くサイクルを作りたい。

もしこのブログを読んでいる古橋研究室の在学生/卒業生がいたら、以下条件を確認してほしい。そして良いなと思ったらぜひ**仲間になろう！**

* 期待する人物像
①古橋研究室を卒業して社会人を1〜2年以上経験していること
②自分の知識やスキルをチームに還元する意思があること

私達はもう学生ではない。
己の専門性や経験値を磨き、社会に還元するフェーズにきている。

これからもテクノロジーが持つ可能性を信じ、かつそれを国境を越えて社会に活かす方法を考えていきたい。

OpenStreetMapとの衝撃的な出逢いを、次の行動へ繋げていきます。

-----
読了ありがとうございました。
生成AI EXPO in 東海 参加日記

# はじめに
本記事は筆者の生成AI EXPO in 東海の参加記となります。

# 生成AI Expo in 東海
以下HP参照
https://aiexpo-nagoya.com/

# イベントを知った理由 
犬山観光をしている最中にからあげさんのアイコンを目にして、イベントが開催されることを知りました。
土曜は犬山、日曜は名古屋でやっているということを知ったので両日参加することにしました。

# 犬山開催
フロイデといういつもお世話になっている犬山の施設で開催。
この日は用事があったのでぬけだして一部の公演だけ聴きに行けました。
中学生の起業家だったり若い人の語り合いを聞いて生成AIに興味がわきました。
仕事関連だとIVRのボイスボットの話などもあり、会社で作ってみたいなーというのもありました。
犬山開催はこのくらいにしておきます。

# 名古屋開催
開催は久屋大通パークで行われました。嫁さんと2人で行きました。カフェでの開催、人がいっぱいでした。
子どもたちが遊んでいたりおしゃれなカフェがあったりで子供を育てるにはいい環境だなあなんて思ったり。
嫁さんは興味がないので公園であそんでもらうことにしました。
からあげさんの公演では生成AIの勉強方法だったり、経歴だったり、素顔だったりを見れて楽しかったです。


# 感想
イベントを通じて生成AIへの興味が湧いてきました。今後は音声認識、LLMなど駆使して会社のプロダクトを良くしていきたいな。。。
Java Silver SE 17（1Z0-825-JPN）に合格しました

先日、「Java SE 17 Programmer I」を受験し、無事に合格することができました。
試験ができてからまだ日が浅いこともあってか、Qiitaにもあまり記事がなかったので、簡単に自分の勉強方法や受けた所感などを書いてみたいと思います。

### 前提
- Javaは実務で2年ほど使用経験あり
- Java SE Bronzeの受験経験なし
- その他のIT系の資格はOracle Bronzeくらいしか持っていません

### 使用した教材
- [徹底攻略Java SE 17 Silver問題集［1Z0-825］対応](https://amzn.asia/d/6w08Amm)
待望のJava Silver SE 17版が2024年10月に出版されました。いわゆる「黒本」です。
試験に合格するだけならこれ1冊で十分だと思います。
### 
- [オラクル認定資格教科書 Javaプログラマ Silver SE 17（試験番号1Z0-825）](https://amzn.asia/d/2QOLwf6)
いわゆる「紫本」です。
黒本だけだと体系的な解説がないので、あらためて知識を整理するために読んでみました。
問題数は少なめなのと、誤植が多いのが難点ですが、ポイントはわかりやすくまとまっていると感じました。

### 勉強方法
基本的にはひたすら黒本で問題を解く→解説を読むを繰り返していました。
苦手な分野は紫本の解説を読んだり、コードを実際に書いて確実に理解するようにしました。
トータルの学習時間は40時間ほどかと思います。黒本は3～4周くらいやりました。
黒本にある問題（模擬試験含む）を、解答の根拠も説明できるくらいのレベルで9割以上解ければ、合格ラインには十分乗るように思いました。
###
ちなみに、試験の前日に初めて紫本の模擬試験×2をやったところ、両方とも正答率が65％以下で非常に焦りました(笑)
当日の試験は80％超えで合格できたので、紫本の模擬試験はやや難易度が高めなように思います。
本番想定で解くというよりは、試験時間の感覚を掴んだり、問題を解くことに慣れる、というつもりで使用するほうがいいかもしれません。（前日にやるのはオススメしません…）

### 問題を解くときのコツ
- mainメソッドから順に処理を追う
黒本に取り組み始めた当初は、問題に大量のコードが出てくると、どこから読んでいいのか迷ってしまいました。
上から順に見ていってもあまりいいことはないので、とりあえずmainメソッドを探して、処理内で使用する順に追っていくほうが理解しやすいように思います。

###
- 選択肢を先に見て、見るべき観点を絞る
よくある受験対策みたいな話です。
Java Silverの問題では、「コンパイルエラーになる」「実行時にエラーになる」といった選択肢が出てくることがあります。
逆にいうと、これらの選択肢がないときは、少なくともプログラムの実行には問題がないということがわかります。
引っ掛けのような問題も多いことから、「コンパイルエラーになるところないかな？」と問題を見ることが多かったのですが、先に選択肢を見ておけば、そんな心配はせずに素直に処理を追うことができます。

### 
どちらも当たり前のことかもしれませんが、試験に出てくるようなコードを読むことに慣れておらず、最初のうちは苦労しました。
この記事が、これから受験する方に少しでも参考になれば幸いです。
タブの表示について

タブとは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/cc60295c-9346-a0a9-8344-b90d5e8672f9.png)

表示の制御はプロファイルで行う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/a59192b5-e047-b936-b919-9eee5e090f29.png)

表示の方法は意外と３つあるので、迷う時がある。
### タブを隠す：
タブ：ない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/07a66727-1d69-6d5b-a213-1126142df440.png)

さらに表示隣の鉛筆マーク「アプリケーションナビゲーション項目を編集」：ない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/57866e6a-be0e-ad7b-bcdc-357c3e77179a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/a58fbbb6-f453-5239-5d5f-8a46abcf7341.png)

アプリケーションランチャーの「すべて表示」：ない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/c98e18e3-0394-dfa4-b5d3-bf8a4b2e5152.png)

### デフォルトで非表示
タブ：ある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/5867e4e4-f2f3-0cde-cd5e-abb0ecd7c18a.png)

さらに表示隣の鉛筆マーク「アプリケーションナビゲーション項目を編集」：ある、**削除できる**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/a97c82ca-2a6f-3d48-8640-d3505f7f1eaf.png)

アプリケーションランチャーの「すべて表示」：ある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/72b159e1-c86f-4b81-e02e-f58eee8991a3.png)

## 結論：
「デフォルトで非表示」と「デフォルトで表示」はほぼ同じ
違いは：
さらに表示隣の鉛筆マーク「アプリケーションナビゲーション項目を編集」：ある、**削除できる**
Amazonbotからの簡易的な防衛術(nginx)

# はじめに

Amazonbotから弊管理下にあるwikiへのアクセスがあまりにもひどい。
数秒に1回、しかも500個以上のIPから分散してbotアクセスしてくるのは、いくらなんでもやりすぎです。
UserAgentでbotだと名乗れば何をしてもいいわけではありません。
本当はこんなことをしなくてもよいようになればいいのですが、しょうがないのでUserAgentを見てbotの場合は簡易的に403を返すようにしました。
ついでに `robots.txt` も設置しておきました。
下記の設定例は、私の方でnginxに行った設定を一般化したものです。

# 各種設定例

```nginx:wiki.conf
server {
    server_name wiki.example.com;

    listen [::]:80;
    listen 80;
    root /var/www/wiki/

    set $is_bot 0;
    if ($http_user_agent ~ (Amazonbot|other_bot_user_agent)){
        set $is_bot 1;
    }

    location ^~ /static/ {
        alias /var/www/internal/static/;
        internal;
    }

    location = /robots.txt {
        rewrite ^(.*)$ /static/robots.txt;
    }

    location / {
        if ($is_bot = 1) {
            error_page 403 /static/bot_403.txt;
            return 403;
        }
    }
}
```

```text:robots.txt
User-agent: Amazonbot
Disallow: /
User-agent: other_bot_user_agent
Disallow: /
```

```text:bot_403.txt
DISALLOWED REQUEST! FOLLOW GUIDANCE ON robots.txt!
```
※お好みで文面を変えたり、任意のHTMLを作成・設定してもよいと思います。

# おわりに

おわりです。
自動運転AIチャレンジsim2023で入賞した話

# はじめに
本記事は自動運転もAIもほとんど触ったことのない筆者が自動運転AIチャレンジでコミュニティ貢献賞・広報賞をとった話になります。

# 筆者スペック
・情報系修士卒、数学未履修、制御工学なにそれ美味しいのレベル
・車載システムのファーム開発に従事していた
・2023年の春あたりにAutowareを知る
・何かAutowareでやってみたかったのにいいコンペとして自動運転AIチャレンジを知る
といった感じです。

# 大会中にやった活動
完走賞欲しさにQiitaのアドベントカレンダー時期に[一人アドベントカレンダー](https://qiita.com/advent-calendar/2023/aichallenge_racing_for_mas)をやりました。
運営からOSS連携やってみると面白いよーという話を聞いたのでOSS連携をやってみることにしました。
もともと経路追従のアルゴリズムにpure pursuitというものがつかわれていたのですがこれをpython roboticsのLQRに置き換えて走らせてみるという活動をおこないました。
アルゴリズムは制御工学無知なのでいまだにLQRのアルゴリズムがよくわかってないです。すみません。
これらの活動が評価されたらしく前述の賞をいただくことになりました。

# 受賞式
賞をいただいたいので東京の四谷にいってきました。
上位入賞された方のお話を聞かせていただき知見がある方すごいとなりました。
時間があったら制御の勉強してみたいですね。

# 2024年自動運転AIチャレンジ
出たかったのですが転職したてかつ業務が忙しいこともあり参加できず。。。
来年か再来年あたりにはまた出たいです。

# 現在の仕事
車載から離れてしまっていて今はIP電話のシステムをRustで作っています。
今後はLLMとか音声認識とかやっていくことになるかもしれないので数学とか勉強しています。
電話で問い合わせするとAIが対応してくれますよね、今後あれをつくってみたいです。目指せ内製化。
Autowareのおかげで数式の勉強とかできているので助かっています。

# おわりに
自動運転AIチャレンジの取り組みは本当にいろいろ知見を得ることができますし何より楽しいです。
みなさんもチャレンジしてみましょう。
Windows で uv の PyTorch インストールエラーに対処

Windows の uv 環境で PyTorch をインストールしようとしてエラーになったので、Python のバージョン指定で対処しました。検索しても同じ状況はヒットしないようなので、参考までに書いておきます。

:::note info
本記事では CPU 動作を想定しているため、CUDA の指定は行いません。
:::

# エラー状況

適当なディレクトリで uv を初期化して torch のインストールを試みます。

```
D:\test>uv init
Initialized project `test`

D:\test>uv add torch
Using CPython 3.13.0
Creating virtual environment at: .venv
Resolved 23 packages in 150ms
error: Distribution `torch==2.5.1 @ registry+https://pypi.org/simple` can't be installed because it doesn't have a source distribution or wheel for the current platform
```

`--index-url` を指定してもエラーです。

```
D:\test>uv add torch --index-url https://download.pytorch.org/whl/cpu
warning: Indexes specified via `--index-url` will not be persisted to the `pyproject.toml` file; use `--default-index` instead.
Resolved 11 packages in 2.11s
error: Distribution `torch==2.5.1+cpu @ registry+https://download.pytorch.org/whl/cpu` can't be installed because it doesn't have a source distribution or wheel for the current platform
```

uv のデフォルトで Python 3.13.0 が使用されていますが、3.13 用の torch が用意されていないためのようです。

# Python バージョンの変更

Python 3.12 系にバージョンを変更します。

```yaml:pyproject.toml（変更箇所）
requires-python = ">=3.12"
```

```
D:\test>uv python pin 3.12
Updated `.python-version` from `3.13` -> `3.12`
```

torch がインストールできました。

```
D:\test>uv add torch
Using CPython 3.12.7
Removed virtual environment at: .venv
Creating virtual environment at: .venv
Resolved 24 packages in 678ms
░░░░░░░░░░░░░░░░░░░░ [0/10] Installing wheels...                                                                        warning: Failed to hardlink files; falling back to full copy. This may lead to degraded performance.
         If the cache and target directories are on different filesystems, hardlinking may not be supported.
         If this is intentional, set `export UV_LINK_MODE=copy` or use `--link-mode=copy` to suppress this warning.
Installed 10 packages in 25.46s
 + filelock==3.16.1
 + fsspec==2024.10.0
 + jinja2==3.1.4
 + markupsafe==3.0.2
 + mpmath==1.3.0
 + networkx==3.4.2
 + setuptools==75.6.0
 + sympy==1.13.1
 + torch==2.5.1
 + typing-extensions==4.12.2
```

# 関連記事

https://qiita.com/7shi/items/0f9c9ff7cf2fcb9597c5

# 参考

https://zenn.dev/mjun0812/articles/b32f870bb3cdbf

https://zenn.dev/hiroga/articles/uv-pytorch-trouble-shooting
ABC382振り返り

ABC382の振り返りです。

## 結果

A,Bの2完でした。くやしい、、

![スクリーンショット 2024-12-07 15.29.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167729/398b7f19-3f46-b942-c026-0d95f3bac01e.png)

![スクリーンショット 2024-12-07 15.28.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167729/20044ef6-63a2-3516-ad60-2db7e24d4fa4.png)

## 解説

### A問題

- 問題
  - https://atcoder.jp/contests/abc382/tasks/abc382_a
- 回答
  - https://atcoder.jp/contests/abc382/submissions/60307649

`@`がどこにあるかを調べるひつようもないです。`.`の数をカウントしてdを足せばよいです。

```haskell
main :: IO ()
main = do
  [n, d] <- getInts
  s <- getLine

  let cnt = length $ filter (== '.') s

  print $ cnt + d
```

```haskell
main :: IO ()
main = do
  [n, c] <- getInts
  ts <- getInts

  print $ fst $ foldl' (\acc@(cnt, curr) t -> if t - curr < c then acc else (cnt + 1, t)) (1, head ts) (tail ts)
```

### B問題

- 問題
  - https://atcoder.jp/contests/abc382/tasks/abc382_b
- 回答
  - https://atcoder.jp/contests/abc382/submissions/60320214

`reverse`して再帰で`@`を`.`に置き換えればよいです。

```haskell
main :: IO ()
main = do
  [n, d] <- getInts
  s <- getLine

  let s' = solve (reverse s) d

  putStrLn $ take (n - length s') s ++ s'

solve :: (Eq t, Num t, Enum t) => [Char] -> t -> [Char]
solve s d = f s [] d
  where
    f s ans 0 = ans
    f (sh : st) ans d
      | sh == '@' = f st ('.' : ans) (pred d)
      | sh == '.' = f st ('.' : ans) d
```

### C問題

- 問題
  - https://atcoder.jp/contests/abc382/tasks/abc382_c
- 回答(upsolved)
  - https://atcoder.jp/contests/abc382/submissions/60350883

最初、これは「おいしさBiの食事に対して、美食度を超えない最大のAiを探せばいい」と考え、これは二分探索だなと思いました。

これを実装すると以下のようになります。

```haskell
main :: IO ()
main = do
  [n, m] <- getInts
  as <- getInts
  bs <- getInts

  let im = IM.fromList as
  　　 ans = [snd $ fromJust $ IM.lookupLE b im | b <- bs]

  mapM_ print ans
```

しかし、これを動かすと3つ目のサンプルケースが通りません。

入力値を
```
10 5
60 83 76 45 70 91 37 58 94 22
70 39 52 33 18
```

とすると、出力値は

```
1
7
4
10
-1
```

となって欲しいのですが

```
5
7
4
10
-1
```

となってしまいます。

なぜこうなるのでしょうか？

それは問題の前提条件
`それぞれの人は、美味しさが自分の美食度以上である寿司が自分の前に流れてきたときはその寿司を取って食べ、それ以外のときは何もしません。`
を考慮しきれていなかったことが原因です。

この条件について考えてみましょう。前の人が先にお寿司を食べてしまうので

`i < i'として、Ai <= Ai' だとするとAi'の人はお寿司を食べられない`

ということになります。（なんとも理不尽です）

例えば、お寿司を食べようとしている人が3人で、

`A1 = 70, A2 = 60, A3 = 90`

だったとします。
この状況でおいしさが70以上のお寿司が出てくると、A1の人が食べてしまうので、A2, A3はお寿司を食べることができません。

お寿司のおいしさが`60 <= Bi < 70`であれば、A2の人はお寿司を食べられますが、A3の人が食べられないのは同様です。

つまり、`A1 <= A3`の時点で、A3の人はお寿司を食べることができないのです。

これを踏まえて、`Ai`のリストを修正する必要があります。
修正方針としては、

`i < i' として、Ai < Ai'となるAi'を全て削除する`

ということになります。

これを実装すると

```haskell
f [] _ _ _ = [(0, -1)]
f (ah : at) (c, d) n m
  | ah < c = (ah, m) : f at (ah, m) n (m + 1)
  | otherwise = f at (c, d) n (m + 1)
```

となり、これだとACします。
全体のコードは以下の通りです。

```haskell
main :: IO ()
main = do
  [n, m] <- getInts
  as <- getInts
  bs <- getInts

  let im = IM.fromList $ f as (2 * 10 ^ 5 + 10, 0) n 1
      ans = [snd $ fromJust $ IM.lookupLE b im | b <- bs]

  mapM_ print ans

f [] _ _ _ = [(0, -1)]
f (ah : at) (c, d) n m
  | ah < c = (ah, m) : f at (ah, m) n (m + 1)
  | otherwise = f at (c, d) n (m + 1)

```

## 全体を振り返って

前提条件を踏まえて考えると解けるのですが、そこに気づくのがなかなか難しい、、
まだまだ精進です。
相対パスと絶対パス

# 目次

[`1`はじめに](#1はじめに)
[`2`パスとは](#2パスとは)
[`3`相対パスと絶対パスについて](#3相対パスと絶対パスついて)
[`4`相対パスと絶対パスの使い分け](#4相対パスと絶対パス使い分け)
[`5`おわりに](#5おわりに)


# `1`はじめに
なぜこの記事を書いているかというと、模写コーデイングをした時にCSSファイルの読み込みができず、解決するまでに5時間ほどかかってしまい、一度知識を整理しときたいと思ったからです。また、相対パスと絶対パスについて分からない人のために記事を書きたいと思います。


# `2`パスとは
パスとは簡単にいうと経路のことで目的のファイルがどのフォルダに保存されているかを示すものです。パスは実行しているファイルから他の場所にあるファイルを実行する場合に目的のファイルを指定するために使われます。<br>下記の場合だと、bootstrap-garalley.htmlファイルからgallery.cssファイルを指定したい時に『パス』を使うイメージ


![9715088F-ED6C-4E7E-98F0-AF6F98A6EBB3_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3585901/83292094-cf3e-4a26-df42-7d9b5c821529.jpeg)


# `3`相対パスと絶対パスについて

まず、相対パスと絶対パスについてネットで調べると下記のような説明がされているかと思いますがイメージは下記の画像となります。

**①絶対パス**
ディレクトリの階層構造の頂点から目的のファイルまでの道筋を、全て省略せずに表記します。



**②相対パス**
相対パスは、現在作業しているファイルの場所から見た、目的のファイルへの行き方を表記します。


![9715088F-ED6C-4E7E-98F0-AF6F98A6EBB3_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3585901/7a66b1ea-05f8-6336-9efb-a3722bef31c1.jpeg)


※1絶対パス　bootstrap/css/gallery.css
※2相対パス  css/garllery.css




# `4`相対パスと絶対パスの使い分け

相対パスと絶対パスのどちらを使用するかはファイルの位置関係や利用目的によります。以下に同じフォルダ内と別のフォルダにある場合で場合分けしていきます。

**I、同じフォルダ内の場合**
**相対パスを使うべき理由**
* シンプルで直感的 
*  同じフォルダ内であればそのままファイル名を書くことで動作します。
* ローカル環境とサーバー環境のどちらでも問題なく機能する。

```
/project
  ├── index.html
  └── style.css
```
```html
<link rel="stylesheet" href="./style.css">
```
※./は省略可　./は同じ階層を意味する

**絶対パスを使うべき場面**
*一般的に同じフォルダ内では絶対パスを使用しない。
ただし、サーバールートからの完全なパスを記載する必要がある場合は例外です。

**II、別のフォルダにある場合**
**ケースA サブフォルダにある場合**


**相対パスを使うべき理由**
* ファイルの位置を基準に分かりやすく書ける
* サーバーやローカル環境を問わず動作する。

```
/project
  ├── index.html
  └── css
      └── style.css
```

```html
<link rel="stylesheet" href="css/styles.css">
```

**絶対パスを使うべき場面**
* サーバー環境で、ルートディレクトリから一貫してパスを記述する場合
* 絶対パスにすることでどのHTMLファイルからも同じパスでアクセス可能　

```
/project
  ├── index.html
  └── assets
      └── css
          └── style.css
```
```html
<link rel="stylesheet" href="/assets/css/style.css">
```

**ケースB:上位ファルダにある場合**
**相対パスを使うべき理由**
* フォルダ階層を遡るパスを記述可能
* HTMLからCSSまでの距離が短くファイルの位置関係がはっきりしている場合は相対パスが適している

```
/project
  ├── css
  │   └── index.html
  └── style.css
```

```html
<link rel="stylesheet" href="../style.css">
```

**絶対パスを使うべき場面**
* サーバー環境でプロジェクト全体を通じて統一的にルートからのパスを使用する場合

```html
<link rel="stylesheet" href="/project/style.css">
```

# `5`おわりに

いかがだったでしょうか？パスの理解はプログラミングを勉強していく上では避けては通れないのでこの機会にマスターしておきましょう。
022 AI屋さんの　LLMに２００万トークン全文入力　野良右衛門＋ブログ編03





022 AI屋さんの　LLMに２００万トークン全文入力　野良右衛門＋ブログ編03


前々回・前回のブログ編の続きです。


---

https://st.bono0.com/nora01

と言うことで、早速サーバーレスにネットワークストレージをマウントしてアプリを動的に更新できる　webアプリの完成です。
詳細は、下記参照。

---

アプリ自体を動的に　追加可能な　ブログを作ります。
　日記のブログではなく
　アプリ自体のブログです。
そこで、ボリュームのマウントをちょっと変えます。
 
　 /app/pages

これでようやく、準備が整いました。
streamlitのpagesディレクトリは、メッチャ便利なディレクトリです。

　クラウドのサーバーレスのcloudrun　と
　docker仮想環境　と
　cloud storage に
　pages ディレクトリ で

動的にwebアプリを　追加・変更可能な
webアプリ自体のブログの完成です。
スクリプト言語の実行ファイルは、普通のテキストなので
やってることは、普通のブログや掲示板と同等です。

見た目は普通ですが
pythonファイルを　pagesディクトりに保存すると
サイドバーから　追加したアプリが利用可能となります。


![スクリーンショット 2024-12-07 15.01.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/a9ffc7a7-41ca-73dc-4608-887713ee9ac9.png)


一度雛形をデプロイすれば
pagesディレクトリに　バンバン　pythonファイルを追加して
webアプリを動的に追加公開が容易に可能となります。
クラウドでのコマンドもデプロイも不要です。
ブログのように、文章（pythonファイル）を追加するだけです。

　直接コードを書いて保存もできるし
　編集も削除もできるし
　ファイルをアップロードもできるし


つまりサーバーレスへのデプロイ作業も　もはや不要となります。

まあ、普通にクラウドの管理画面からストレージにアップロードしてもいいのですが、
ここは、ブログ風に自作のweb画面からのアップロードとしておきます。


　 
 
 streamlit
 Overview of multipage apps


https://docs.streamlit.io/develop/concepts/multipage-apps/overview


![スクリーンショット 2024-12-07 14.52.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/6876282e-1b8a-a24f-bdd8-de8b4ec78222.png)



注記：
　streamlitのマルチアプリ化
　通常、１URL毎に１webアプリ　のstreamlitですが
　マルチページアプリ機能を使うことで
　複数の個別のwebアプリを　まとめて公開することができます。
　複雑なメニューなどは不要です。
　全自動でサイドバーに個別のアプリが追加されます。
　開発途中のバージョン違いを片っ端から放り込むのに　便利な機能です。








目次

https://qiita.com/bono0/items/dc1d000c98af7e07c9a7



今回も、デプロイ不要の　webアプリ＋ブログ　が

　022 AI屋さんの　LLMに２００万トークン全文入力　野良右衛門＋ブログ編03

無事に完成しました。おめでとうございます。





ー続くー
pytest.ini で簡単にテストを管理する方法とカバレッジレポートの設定

# はじめに

pytestを使用していると、コマンドラインオプションを毎回指定するのが面倒になることがあります。pytest.iniを使用すると、よく使用するオプションをプロジェクトのデフォルト設定として定義できます。


# pytest.iniとは

pytest.iniは、pytestの設定ファイルです。プロジェクトのルートディレクトリに配置することで、プロジェクト固有の設定を定義できます。

https://docs.pytest.org/en/stable/reference/customize.html#pytest-ini

# 使用例


## 1. テスト対象のファイルを作成（準備）

次のようなフォルダ構成でファイルを作成します。

```
root
│── pytest.ini
│── src/
│   └── calc.py
└── test/
    └── test_calc.py
```

テスト対象のファイルは次のとおりです。
簡単な関数を2つ作成します。

```calc.py
# 足し算
def add(x, y):
    return x + y

# 引き算
def subtract(x , y):
    return x - y
```

テストコードは下記の通りです。

```python:test_calc.py
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.calc import add, subtract

def test_add():
    assert add(1, 2) == 3

def test_subtract():
    assert subtract(3, 2) == 1
```


## 2. pytest.iniの作成


プロジェクトのルートディレクトリにpytest.iniファイルを作成します。

:::note warn

pytest.iniはプロジェクトのルートディレクトリに配置する必要があります

:::

- addopts
    - -v：詳細なテスト結果の表示
    - --cov=src：srcディレクトリのカバレッジを計測
- python_files：テストとして認識するファイル名
- testpaths：テストファイルを含むディレクトリ


```python:pytest.ini
[pytest]
addopts = -v --cov=src
python_files = test_*.py
testpaths = test
```

:::note info

`--cov-report` のオプション
カバレッジレポートの出力形式としていくつかのオプションが利用できます。
- --cov-report=term：カバレッジ結果をターミナルに表示
- --cov-report=json：JSONフォーマットでカバレッジ結果を出力

・・・など

参考：https://pytest-cov.readthedocs.io/en/latest/reporting.html

```:オプション
pytest --cov-report html
        --cov-report xml
        --cov-report json
        --cov-report lcov
        --cov-report annotate
        --cov=myproj tests
```
> These four report options output to files without showing anything on the terminal:
https://pytest-cov.readthedocs.io/en/latest/reporting.html

上記のオプションでは、レポート結果はターミナルではなくファイルに出力されるようです。

:::


## テスト実行

次のコマンドでテストを実行します。

```python
pytest
```

上記コマンドを実行すると結果として下記のログが出力されます

```
cachedir: .pytest_cache
rootdir: XXXXX
configfile: pytest.ini
testpaths: test
plugins: cov-5.0.0
collected 2 items

# 2つのテスト
test/test_calc.py::test_add PASSED                                                                                    [ 50%] 
test/test_calc.py::test_subtract PASSED                                                                               [100%] 

---------- coverage: XXXXX -----------
Name          Stmts   Miss  Cover
---------------------------------
src\calc.py       4      0   100%
---------------------------------
TOTAL             4      0   100%
```

このログでは下記の事が分かります。

- 2つのテストがすべて成功（PASSED）
- テスト対象の関数（add, subtract）のカバレッジ100%達成

テスト実行時にキャッシュとカバレッジファイルが生成されるので必要であれば .gitignore に追加することをお勧めします。

## レポート結果をJSON、HTML出力にした場合

レポート結果をHTMLとJSONに出力されるように設定します。
```
addopts = -v --cov-report=html --cov-report=json
```

テスト実行後、htmlcov/ディレクトリに詳細なカバレッジレポートが生成されます。
index.htmlをブラウザで開くと、カバレッジの詳細を確認できます。

```:HTMLレポート
root
│── htmlcov/
│   └── index.html
└── ...
```

```:JSONレポート
root
└── coverage.json
```

# 参考

- https://docs.pytest.org/en/stable/reference/customize.html#pytest-ini
- https://pytest-cov.readthedocs.io/en/latest/reporting.html
AWSのWell-Architected Frameworkをインチキ猛虎弁で解説するで

AWSのWell-Architected Framework（ウェルアーキテクテッドフレームワーク）ってあるやろ？

けど、公式のドキュメント読んでもさっぱり覚えられんやん。結局何ゆうてんの？って思わん？

要はな、クラウド上でシステムを作ったり動かしたりする時に、**「これやっといたら失敗せんで!!」** みたいなベストなやり方を教えてくれるガイドみたいなもんやねん。

これには **「6つの柱」** っちゅうもんがあって、それぞれが大事なポイントやねんけど、今日は誰でもわかるようにサクッと説明するで！

---

### 1. **運用上の優秀性（Operational Excellence）**
って言われても早速わからんやろ!?
これな、**「どうやって毎日システムを上手に動かすか」** っちゅう話やねん。  
例えばやな、しんどい作業をロボットみたいに自動化してくれる仕組みを作るとか、失敗した時にすぐ直せるようにしておくとかや。  
部活で言うたら、「毎日の練習メニューを作って、失敗した試合から学んで次に活かす」みたいな感じやな。

---

### 2. **セキュリティ（Security）**
これはな、**「データとかシステムを泥棒から守ろう！」** っちゅうことや。  
例えばやで、大事な情報には鍵（パスワード）をつけたり、誰が何したかちゃんと記録しとくとか。  
スマホにロックかけるのと一緒やな。「安心・安全が命」ってことや。

---

### 3. **信頼性（Reliability）**
って言われても「何の信頼性やねん」って思うやろ？
これな、**「システムが壊れてもすぐ治るようにしとこ！」** って話や。  
例えば、ジュースの自販機が故障してもすぐ修理してくれるとか、近くに別の自販機があるみたいな仕組みを作るねん。  
「あれが壊れてもこれがあるから大丈夫」っちゅう感じや。

---

### 4. **パフォーマンス効率（Performance Efficiency）**
…意味わからんやろ?ワシも全然わからんかった。
これはな、**「無駄なく効率よく動かそう」** っちゅうことやねん。  
たとえば、クーラーを人が多い時だけつけるとか、最新の省エネ家電を使うみたいな感じや。
AWSは身の丈にあったちょうどいいマシンを選べたりすんねん。
「賢く動いて、余計なエネルギー使わんようにしよ」ってことやな。

---

### 5. **コスト最適化（Cost Optimization）**
これはシンプルや！**「お金の無駄遣いすな！」** ちゅう話や。  
たとえば、部屋に誰もおらんのに電気つけっぱなしやったらもったいないやん？  
AWSでも同じで、使ってへんサーバーは切っとくとか、安くなるプランを選ぶとかするねん。  
「節約は美徳やで！」っちゅう話や。

---

### 6. **持続可能性（Sustainability）**
これは最近入った柱やな。**「地球に優しくしよな」** って話や。
たとえばやな、電気を無駄に使わんようにしたり、自然エネルギーを使うとかやな。
ぶっちゃけ、「パフォーマンス効率化」や「コスト最適化」とかぶってる気するけどなｗ
エコバッグ持って買い物行くみたいなもんや。「地球さん、いつもありがとう」って気持ちやな。

---

### 結論
AWSのWell-Architected Frameworkを最後にまとめるとやな、  
**「安全で壊れへん、しかもお金も無駄にせん、エコなシステムを作るための秘伝のタレ」** みたいなもんや。  
これ守ったら、クラウドのシステムをめっちゃ賢く作れるってことやで！

「せやけど、これ守らんかったらどうなるん？」って？  
そら、システム壊れたり、お金めっちゃかかったりして、上司や顧客に怒られるで！  

まぁ、クラウド使うならこのフレームワーク、頭の片隅に置いといたらええで！
kaggle　tutorial　の一覧

kaggleには公式が用意した複数のチュートリアルと、公式推奨のコミュニティが作った複数のガイドがあります。今日はtutorialの一覧と一言解説・進む順番をまとめて行きます。


## tutorial初心者向け

始めの２つはどちらもpythonそのものについての学習

https://www.kaggle.com/learn/intro-to-programming

https://www.kaggle.com/learn/python

データをpandasの表でもらうこと、評価関数、randam forestあたり

https://www.kaggle.com/learn/intro-to-machine-learning

## tutorial 中級者向け

deeplearningの入門、パーセプトロンの解説

https://www.kaggle.com/learn/intro-to-deep-learning

テストデータの分割やXGBoostの使用例

https://www.kaggle.com/learn/intermediate-machine-learning

pandasのさまざまな機能の紹介

https://www.kaggle.com/learn/pandas


## tutorial 上級者

時系列データの取り扱い

https://www.kaggle.com/learn/time-series

特徴量エンジニアリング　自分でDataFrameに新しい特徴量を加える(解説済み)

https://www.kaggle.com/learn/feature-engineering

画像分類の初歩についてLv：MNIST,CIFAR-10あたり

https://www.kaggle.com/learn/computer-vision



上から下に向かって進んでいくのが公式推奨ルートです。途中で疑問がたくさん出てくると思いますので、そのキーワードを調べると大学の授業資料などが引っかかるのでそれを読むと理解が深まります。そして、個別の細かい理解をするにはやはりオライリーで本を読むのが最適かと思います。tutorialはそれぞれの分野への入門、DataScience全体への理解を深めてくれる教材が多い印象です。

https://www.oreilly.co.jp/index.shtml

tutorialについても上の一言解説を見て知っている部分が多いと思えばSKIPするのはありでしょう。pythonを読める人が改めてtutorialをこなす必要は、修了時にもらえる認定証が欲しいなど以外ではないです。
pyenvの仮想環境をGitで管理する方法

# pyenvの仮想環境をGitで管理する方法

## 結論
- Gitに含めるもの: .python-version, requirements.txt
- Gitに含めないもの: 仮想環境そのもの

##### 補足
##### .python-version
- 仮想環境名やPythonバージョンを記録したファイル。
- 他の開発者が同じリポジトリをクローンしたとき、このファイルに基づいて自動的に環境を切り替えられる。
###### requirements.txt
- 仮想環境でインストールされたパッケージの依存関係を記録したファイル。
- 他の開発者が仮想環境を再現するために必要。


## 仮想環境そのものはGit管理しない
- pyenvによる仮想環境は多数のファイルを含むため、Gitで追跡するとリポジトリが肥大化します。
- 仮想環境を直接共有する代わりに、環境再現に必要な情報（Pythonバージョンやパッケージ一覧）をコードとして管理することで、他の開発者が容易に同じ環境を構築できます。

## 基本的な手順

### 1. 仮想環境を作成する
指定したPythonバージョンで仮想環境を作成します。
```bash
pyenv virtualenv <Pythonのバージョン> <環境名>
```

### 2. プロジェクトディレクトリへ仮想環境を適用する
プロジェクトディレクトリで以下を実行し、.python-versionファイルを生成します。
```
pyenv local myproject-env
```
.python-versionはGitで管理することで、他の開発者が同リポジトリをクローンした際に、pyenv localを通じて同じ仮想環境を再現しやすくなります。

### 3.依存パッケージを管理する
```
pip install パッケージ名
```
※pyenvは、virtualenvやvenvのように仮想環境名をプロンプトに自動で追加しません。そのため、仮想環境が切り替わっていても、プロンプトが変化しません。


### 4.依存関係を記録
プロジェクトに必要なパッケージを記録します。
```
pip freeze > requirements.txt
```

### 5.	".python-version" と "requirements.txt" をGitに追加
```
git add .python-version requirements.txt
git commit -m "Add pyenv configuration and dependencies"
```

## 仮想環境を復元する方法
クローンしたディレクトリで以下を実行してください。
```
#仮想環境の作成
pyenv virtualenv <Pythonのバージョン> <仮想環境名>
#プロジェクトディレクトリに仮想環境絵を指定
pyenv local <仮想環境名>
#依存パッケージのインストール
pip install -r requirements.tx
```
プログラミング勉強メモ( コードを書く前段階 )

## 実装する前に確認する前提条件
- 定義が必要な関数は何か？
- 渡せる引数は何か？
- 関数から返す戻り値は何か？

## コードを記述するステップを考える
- 要件を実現するために必要な処理を小さなステップに分解する
- 条件分岐や繰り返しの要/不要や、それらをどのように使うのかを考える

## 上手くいかない時の対処法
- printデバッグを実施する
- エラーメッセージを調べる
【ユーザ管理】ワークグループって・・・？

# はじめに

AzureのEntra ID周りを勉強していた時のことです。
オンプレのADサーバについての理解に乏しいと思ったのでAD周りの勉強しました。

その際、ユーザ管理の方法にADサーバ以外の方法として「ワークグループ」があるということを知りました。当時「なんだそれは・・・！？」と思ったので以下に備忘録としてまとめます。

# ユーザ管理の方法

Windowsを使う場合、ユーザー管理のしくみには大きく次の２つの種類の方法があります。

1. ワーク グループ
1. ドメイン

# ワークグループ

#### ワークグループとは
ワークグループとはユーザ管理をサーバなしで行う方法です。
具体的には以下のようになります
・管理したいコンピュータのワークグループ名を同じ名前にしておきます
・各コンピュータへユーザアカウントのデータベースを保存しておきます
・ユーザがコンピュータにログオンする際、ローカルのユーザアカウントのデータベースを参照して認証させます
※同一ネットワークにコンピュータが存在する前提です。

なお、手元のPCにログインする際はそのPCに保存されているデータベースを参照します。
また、サーバにアクセスする際はサーバに保存されているデータベースを参照させます。

自分のPCのワークグループが何になっているか確認するには以下を確認します。
コントロールパネル＞システム＞ドメインまたはワークグループ
![workgroup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248327/f3d8b4e7-86f8-c7db-54c8-e20e113406a1.png)

※デフォルトでは画像のように「WORKGROUP」になります

なお、データベースはすべてローカル保存なので編集するには各コンピュータのデータベースを直接編集する必要があります。
これでは手間なので、よく使われるＡＤサーバを使うわけですね。

#### 実は意識していなかっただけで使っていた機能だった

ここまで勉強していて、気づいたのですが
私はよく「ローカルユーザ」と呼んでいる機能だと気づきました。

よくパソコン購入すると、最初にユーザIDとパスワードを設定しますよね。
まさにこれがワークグループという方式のユーザ管理の方法だったわけです。

驚き（笑）

# 最後に

意外とワークグループという名称を知らずに使用している方もいるかと思いますので、まとめてみました。
実はもともと、「Azure上からワークグループの認証って突破できるのかな？」の思ったのがきっかけで調査しましたので、機会があればそれも記事にしようと思います。
これを知らないと損！開発者なら知っておきたいGitコマンド10選

## 実は、この記事

https://qiita.com/muu3/items/ea1e616ffae5b34dfa18

という選手権で生成AIが考えたタイトルになります！
さぁ、生成AIの筋肉、ならぬ「バズマッスル」の真価を見せてもらいましょう:tada:

## はじめに
Gitは非常に強力なツールですが、多くの開発者が使うのは基本的なコマンドだけでその真価を発揮できていません。`git commit`や`git push`だけでなく、知っておくと開発効率が劇的に向上する隠れたコマンドがたくさんあります。
本記事では、`git bisect`を使ったデバッグ方法や、`git stash`を活用した効率的な作業方法など、実際の開発現場で役立つ10のコマンドを紹介します。

## Gitコマンド10選
### 1. git bisect
不具合を特定するために、良いコミットと悪いコミットを効率的に探すバイナリ検索ツール
```bash
git bisect start
git bisect bad
git bisect good <commit-hash>
```

### 2. git stash
現在の作業状態を一時保存し、ワーキングツリーをクリーンにする
```bash
git stash save "WIP: fixing issue"
git stash list
git stash apply
```

### 3. git reflog
過去のすべてのHEADの移動履歴を表示する
失ったコミットを見つけるのに便利
```bash
git reflog
git checkout <commit-hash>
```
    
### 4. git cherry-pick
特定のコミットを選んで、現在のブランチに適用する
```bash
git cherry-pick <commit-hash>
```

### 5. git blame
ファイルの各行を最後に変更した人とそのコミットを表示する
```bash
git blame <file-name>
```
    
### 6. git clean
追跡されていないファイルやディレクトリを削除して、リポジトリをクリーンにする
```bash
git clean -f -d
```
    
### 7. git log --oneline --graph
コミット履歴を簡潔にツリー形式で表示する
```bash
git log --oneline --graph --all
```

### 8. git reset
指定したコミットまでリポジトリをリセットする
```bash
git reset --soft <commit-hash>  # コミットをリセット（作業状態は保持）
git reset --hard <commit-hash>  # 作業状態を含めリセット
```

### 9. git diff
ワーキングツリーとインデックスの間、または2つのコミット間の差分を表示する
```bash
git diff HEAD
git diff <commit-hash1> <commit-hash2>
```

### 10. git archive
特定のコミットの内容をZIPやTARファイルとしてエクスポートする
```bash
git archive -o latest.zip HEAD
```

## まとめ
Gitを使いこなすには、基本的なコマンドだけでなく、高度な機能を活用することが重要です。
この記事で紹介した10のコマンドを取り入れることで、作業効率が向上したりデバッグが速くなったり、チームメンバーを驚かせることもできるかもしれません！
ぜひ、これらのコマンドを試してみて、開発プロセスをよりスムーズにしてみてください。

最後までお読みいただき、ありがとうございました。この記事が読んでくださった方のお役にたつことを祈ります:blush:
RustとWebAssemblyで絵文字Video作ってみた

# はじめに

前回(下記)で、WebCameraの映像をAsciiアートに変換してみたので

今回はWebCameraの映像を絵文字に変換するツールを作ってみる。

https://qiita.com/shisojuice/items/ce8be8c1f6ac303aa16f

# プロジェクトの作成

大まかな手順としては

指定されたドットサイズでセルに分割して、

セル単位でRGBが各色の絵文字パレットに近いものが出力される。

## 絵文字の設定

cell に、もし赤っぽい色のピクセルデータが多数含まれるときは

emoji_chk = true の場合、 🟥 を返し、

emoji_chk = false の場合は 😡 を返しますような関数を作成する。

その他の絵文字についても色に近い絵文字を選出して、設定しておく。

(絵文字は環境によって異なるのでデバイスによっては想定外の色になっているかもです🙇‍♂️)

```rust:lib.rs

// Cellの色が近い下記の絵文字を返す
fn analyze_cell(cell: &[u8],emoji_chk:bool) -> char {
    let mut r_sum: u32 = 0;
    let mut g_sum: u32 = 0;
    let mut b_sum: u32 = 0;
    let mut count: u32 = 0;

    for i in (0..cell.len()).step_by(4) {
        r_sum += cell[i] as u32;
        g_sum += cell[i + 1] as u32;
        b_sum += cell[i + 2] as u32;
        count += 1;
    }

    if count == 0 {
        return '⬜'; // セルが空の場合は白を返す
    }

    let r_avg = r_sum / count;
    let g_avg = g_sum / count;
    let b_avg = b_sum / count;
    if emoji_chk{
        match closest_color(r_avg, g_avg, b_avg) {
            (255, 119, 99) => '🟥',   // 赤
            (255, 155, 59) => '🟧',   // オレンジ
            (243, 191, 63) => '🟨',   // 黄色
            (131, 211, 19) => '🟩',   // 緑
            (0, 235, 219) => '🟦',   // 青
            (63, 191, 255) => '🟪',   // 紫
            (134, 74, 43) => '🟫',   // 茶
            (0, 0, 0) => '⬛',         // 黒
            (255, 255, 255) => '⬜',   // 白
            _ => '⬜',                // デフォルトは白
        }
    }
    else{
        match closest_color(r_avg, g_avg, b_avg) {
            (255, 119, 99) => '😡',   // 赤
            (255, 155, 59) => '🍊',   // オレンジ
            (243, 191, 63) => '⭐',   // 黄色
            (131, 211, 19) => '🤢',   // 緑
            (0, 235, 219) => '🥶',   // 青
            (63, 191, 255) => '😈',   // 紫
            (134, 74, 43) => '💩',   // 茶
            (0, 0, 0) => '👾',         // 黒
            (255, 255, 255) => '👻',   // 白
            _ => '👻',                // デフォルトは白
        }
    }

}
```

(まだまだ微妙なところもあるが)とりあえず完成！

# 今回の成果物

デモURL

https://shisojuice.github.io/Rust_VideoEmoji/


デモ画像

![RustとWebAssemblyで絵文字Video作ってみた_01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/03af8a19-efe7-1443-5b2f-6bf32edcfdd6.gif)

![RustとWebAssemblyで絵文字Video作ってみた_02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/b4015f4a-22be-72cc-71e9-1b307dbe5f68.gif)

ソース

https://github.com/shisojuice/Rust_VideoEmoji


# まとめ

今回は入力映像を絵文字のVideoにしてみた。

思いのほか、色調整が難しく、照明やカメラの露出などで

色が大きく変わってしまったので、時間があればリベンジしたい。