OmniAICreator/Qiita-1.07M huggingface dataset:
仮想テープ装置（VTL：Virtual Tape Library）とは

# はじめに
メインフレームネタになります。
特に富士通メインフレームでバックアップデータを保存先となる仮想テープ装置についてまとめたいと思います。

# 仮想テープ装置とは
仮想テープ装置は、英語で書くと*Virtual Tape Library*、略してVTL装置と呼ばれます。
端的に言えば、データを保存する媒体です。
データを保存する先としては、現代であればS3のようなクラウドストレージ、ローカルであればSSDやHDDだと思います。
昔々、1990年代でしょかね:thinking:、データを保存する先としてカセットのようなテープ装置が使われていました。
私も見たことないですが。

https://museum.ipsj.or.jp/heritage/FACOM603F.html

テープだとテープが終わったら、掛け替えないといけないです。
現代だとテープがSSDやHDDに変わっています。また複数台のDISKをひとまとめにして1台の媒体として扱えるようになっていたりします。
そのため、ディスク上に仮想的にテープ装置を構築するので、仮想テープ装置と呼ばれています。

読込、書込みが遅いため、データのバックアップ保存先として使われることが多いかと思います。
バックアップとして使わるので、世代管理を行うことができます。

# VTLカタログ情報加工ツール
VTLのマスタ情報をダンプしたデータからデータセット名とバックアップされる世代の上限値を抽出するPythonプログラムを作ってみました。
メインフレームマイグレーションでバックアップデータ移行対象調査にて活用できるかもということで作成してみました。

```python:VTLカタログ情報からデータセット名とバックアップされる世代の上限を取得
infile = './input.txt'
outfile='./output.txt'
datasetFlag = 0

outFile = open(outfile,'w',encoding='utf-8')

with open(infile) as file_object:
    for line in file_object:
        if 'GDG BASE' in line:
            target='------'
            idx = line.find(target)
            dataName = line[idx + len(target):]
            datasetFlag=1
        
        if datasetFlag == 1:
            if 'LIMIT-----------------' in line:
                targetst='-----------------'
                idxst = line.find(targetst)
                targetend='SCRATCH'
                idxend = line.find(targetend)
                datalimit = line[idxst + len(targetst):idxend]
                datasetFlag=0

                outFile.write(f'{dataName.strip()},{datalimit.strip()}\n')
outFile.close()
```

＜リポジトリ＞

https://github.com/LittleBear-6w6/MainframeMigration/tree/main/PutVTLInfo
ブラウザでのJavaScirptの動作について

## JSの実行にかかわるもの
- JavaScript エンジン
- Web APIs
- コールバックキュー
- イベントループ

## JavaScriptエンジン
### 仕事
JSを解析→コンパイル→実行

ブラウザによって使用されているJavaScriptエンジンは異なる。
Googleであれば、V8エンジン。

### JITコンパイル
プログラミング言語には、コンパイラ言語とインタプリタ言語がある。

コンパイラ言語：実行前に実行可能ファイルへと変換し、それを実行する形式。
インタプリタ言語：実行しながら評価する形式。

JavaScriptはその中間である、JITコンパイラが使用されている。
JITコンパイラは頻繁に実行されるコードや実行に時間がかかるコードをマシンコードにコンパイルする形式。

### 実行までの流れ

#### parsing
コードを解析し、AST（抽象構文木）と呼ばれるデータ構造を作成する。

#### compile
頻繁に実行されるコードをコンパイルする。

#### execute
作成したコードを実行する。
コンパイル部分はそのまま実行。
そうでない部分は評価し実行。

#### optimized
頻繁に実行されるコードなどコンパイルすべき部分を決定する。

### Web APIs
ブラウザによって提供されているAPI。
DOMやFetch、consoleなどがある。

### コールバックキュー
JavaScriptエンジンは同時に一つの処理しか実行できない。
次に処理されるものが待機する場所。

### タスクキュー
- ユーザーイベント（クリック、キーボード入力など）
- setTimeoutやsetIntervalなどのタイマー
- I/O操作（ネットワークリクエスト、ファイル読み込みなど）
上記のコールバック関数のことをタスクと呼び、タスクキューに格納される。

#### マイクロタスクキュー
- Promiseの処理（then、catch、finally）
- MutationObserverのコールバック
- queueMicrotask関数
上記のコールバック関数をマイクロタスクと呼び、マイクロタスクキューに格納される。


上記二つのキューの違いは優先度。
マイクロタスクキューの方が高い。

### イベントループとは
コールスタックが空になるたびにコールバックキューからタスクを取り出して、追加すること。
[Unity]UnityNetcodeをちょっと触ってみたい人用の記事

# 概要
ネットワークマルチプレイを実現できるUnityNetcodeに興味があってちょっと試してみたい！という方に向けて書いた記事です。

# 本文
## パッケージをインストールする
Unityで新規プロジェクトを作成します。次にメニューからWindow > Package Managerと辿って「Netcode for GameObjects」をインストールします。

:::note info
Netcodeには二種類ありますがECSに対応した「Netcode for Entities」は今回扱いません。「Netcode for GameObjects」を選んでください。
:::

![スクリーンショット 2024-06-15 151612.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/50dd41fd-8c71-003a-236f-acad0ff8823b.png)



## NetworkManagerを作成
Hierarchyで右クリック > Create Emptyを選択して「NetworkManager」を作成します。InspectorからAddComponentを押したらNetwork Managerを選択します。

![スクリーンショット 2024-06-15 152718.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/c019ebcd-5053-473c-cf84-f12e07ea3691.png)

追加されたNetwork Managerコンポーネントを見てみると「netcodeにはUnity Transportが必要です」と警告が表示されています。その下の「Select transport...」を押して「UnityTransport」を選ぶと自動でUnity Transportを追加してくれます。

![スクリーンショット 2024-06-15 153242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/c73ce5eb-8c65-ba5c-bdbc-8a06496e62a5.png)

netcode上で操作するプレイヤーキャラクターのPrefabを用意します。
Project上で右クリック > Create > Prefabを選び、「NetworkPlayer」を作成します。

![スクリーンショット 2024-06-15 153958.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/7dc7d33d-cac4-adf7-8e99-6c20c5475905.png)

そしてAddComponentから「NetworkObject」を選択します。（これが無いと実行時にエラーが表示されます）

![スクリーンショット 2024-06-15 154715.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/a8774712-d175-7a67-3a20-55c332575a72.png)


NetworkManagerのPlayer Prefab欄にNetworkPlayerをアタッチします。

![スクリーンショット 2024-06-15 154309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/0ae32556-2d68-600f-ab1f-e2fc7a9fab87.png)

## 実行
ここまで準備出来たら、後は実行します。HierarchyのDontDestroyOnLoadの中にNetworkManagerがあるので選択します。NetworkManagerコンポーネント内のStartConnectionにある「StartHost」を押すとNetworkPlayerが画面上に登場します。これでネットワーク上にプレイヤーキャラクターが登場しました:tada:
今回はここまでの紹介ですが、（StartClientを選んで）他のプレイヤーも接続されたらお互いのキャラクターが確認できる状態になります

![スクリーンショット 2024-06-15 155349.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/d2c929a3-5e38-b178-f6aa-cca7c7a78ca5.png)

３Dオブジェクトを設定したらこんな感じにわかりやすくなると思います！（ニワトリプレイヤーが登場しました）

![スクリーンショット 2024-06-15 161644.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/5543724d-b71d-2fdb-bdc8-41b154bc2e69.png)

:::note info
今回のNetworkManagerのStartConnectionボタンは簡易的なテスト用のものなので、実際にはコード上から接続処理をする事になります。
:::

# UnityNetcode関連記事目次
[1.UnityNetcodeをちょっと触ってみたい人用の記事](https://qiita.com/kazuma_f/items/dd88c7132c343500702e)　← :triangular_flag_on_post:
[2.UnityNetcodeでマルチプレイヤーを試してみる記事](https://qiita.com/kazuma_f/items/e8b0fd9bb6a8069f3d36)
[3.UnityNetcodeのマルチプレイヤーで位置を同期してみる](https://qiita.com/kazuma_f/items/bd57bc2c18fd0dfa9c71)
[4.UnityNetcodeのマルチプレイヤーで変数を同期してみる](https://qiita.com/kazuma_f/items/907b01705e78bd199fdd)
【ChatGPT＋DALL-E3】水着がOK？


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

　今回は、水着が描けるようになっていた、というお話。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はあります。　あしからず。
:::

　ニュースはないので
　　本題です。

　今回は、水着の描画です。

　以前はダメだった
　　はずなのですが、
　　　今は描画できます。

　ちょっと
　　試してみました。
***
***user***
プールで游ぶビキニ姿の若い女性。描画

***GPT-4***
（DALL-E3に渡る）
申し訳ありませんが、画像を生成する際に問題が発生しました。他にお手伝いできることがありましたら、教えてください。

***GPT-4o***
![A_young_woman_in_a_bikini_swimming_in_a_pool.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/be1d2b9a-9f3f-8083-1c19-6e9640a830c8.jpeg)
***

　ふむ、イケますねぇ。

　水から上がって
　　もらってもOKでした。

　さすがに
　　下着はダメでした😅

　まぁ、
　　わかってましたけどね。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
特定の条件で集約し、最小値を持つ行を取得する方法

データベースで作業する際に、特定の条件に基づいて集約し、その中で最小値を持つ行を取得したいことがあります。
例えば、特定の`category`が設定されている場合に、その中で`item_id`が最も小さい行を取得したい場合です。
今回はその方法について解説します。

### 例: 集約して最小の`item_id`を持つ行を取得する

まず、以下のようなサンプルデータがあるとします。

```sql
CREATE TABLE sample_table (
    category VARCHAR(50),
    product_name VARCHAR(50),
    price DECIMAL(10, 2),
    supplier VARCHAR(50),
    stock INT,
    location VARCHAR(50),
    item_id VARCHAR(10)  -- item_idは文字列として扱います
);

INSERT INTO sample_table VALUES
('Electronics', 'Smartphone', 599.99, 'Supplier A', 100, 'Warehouse 1', '1'),
('Electronics', 'Smartphone', 599.99, 'Supplier A', 100, 'Warehouse 1', '2'),
('Furniture', 'Chair', 49.99, 'Supplier B', 200, 'Warehouse 2', '1'),
('Furniture', 'Chair', 49.99, 'Supplier B', 200, 'Warehouse 2', '3'),
('Appliances', 'Refrigerator', 299.99, 'Supplier C', 50, 'Warehouse 3', '-');
```

このデータセットから、各`category`ごとに`item_id`が最も小さい行を取得したいとします。
`item_id`が「-」の場合も考慮する必要があります。

### サブクエリを使用した対応策

以下に示すSQLクエリでは、サブクエリを使用して各グループ（`category`、`product_name`、`supplier`、`location`の組み合わせ）ごとに最小の`item_id`を持つ行をフィルタリングしています。

```sql
SELECT 
    category,
    product_name,
    price,
    supplier,
    stock,
    location,
    item_id
FROM 
    sample_table t1
WHERE 
    item_id = (
        SELECT MIN(item_id)
        FROM sample_table t2
        WHERE t2.category = t1.category
          AND t2.product_name = t1.product_name
          AND t2.supplier = t1.supplier
          AND t2.location = t1.location
    )
ORDER BY
    category ASC;
```

このクエリのポイントは、`item_id`が文字列として扱われるため、「-」は他の文字列よりも小さい値として扱われます。
したがって、`item_id`が「-」の場合はそれが最小値として選択されます。

### 結果

このクエリを実行すると、各グループごとに最小の`item_id`を持つ行だけが選択されます。
例えば、上記のサンプルデータの場合、以下のような結果が得られます。

```plaintext
category    | product_name | price  | supplier  | stock | location   | item_id
------------|--------------|--------|-----------|-------|------------|--------
Appliances  | Refrigerator | 299.99 | Supplier C| 50    | Warehouse 3| -
Electronics | Smartphone   | 599.99 | Supplier A| 100   | Warehouse 1| 1
Furniture   | Chair        | 49.99  | Supplier B| 200   | Warehouse 2| 1
```

### まとめ

この方法を使用することで、SQLの`SELECT`句内で特定の列（この場合は`item_id`）を使用せずに、特定の条件に基づいて最小値を持つ行を取得することができます。
サブクエリを活用することで、柔軟かつ効率的にデータを集約・フィルタリングすることができます。特定の値（この場合は`item_id`が「-」）を特別な扱いにする必要がない場合、このように簡潔なクエリで目的を達成できます。

以上
Flutterでチーム開発（個人開発）するときのgitignore（自分用）

## 追記(2025/1/6)
gitignore.ioというサイトが便利でしたので共有です
下記のサイトでFlutterと入力　=> [作成する]ボタンから
gitignoreが生成されるので、そちらを使ったほうが良いかもしれません

https://www.toptal.com/developers/gitignore

# ＊＊envなど大切なものは別途追記してください＊＊
あくまでも参考程度にお願いします。責任は負いかねます

```
# Miscellaneous
*.class
*.lock
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

# Android related
**/android/**/gradle-wrapper.jar
.gradle/
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
**/android/key.properties
*.jks

# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/ephemeral
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
*.xcodeproj/*
!*.xcodeproj/project.pbxproj
!*.xcodeproj/xcshareddata/
!*.xcworkspace/contents.xcworkspacedata

# Google Services (e.g. APIs or Firebase)
google-services.json
```
ファイルの最終は改行を入れてほしい件

GitHubのWebUIでファイルを編集するときに、ファイルの最終行に改行がないと警告が出ますよね。

筆者もエンジニアで仕事をし始めたてのときに先輩から「ファイルの最終行に改行を入れておくように」と言われたことがあります。

これがなぜなのかを調べましたので備忘録として残しておきます。

## POSIXの規定

POSIX（Portable Operating System Interface）は、UNIX系OSの標準化を目指した規格です。

つまりUNIX系OSで動くプログラムを書くときにはPOSIXの規定に従うことが望ましいということになります。

## 仕様を見てみる

https://pubs.opengroup.org/onlinepubs/9699919799/

を見てみると

```
3.206 Line
A sequence of zero or more non- <newline> characters plus a terminating <newline> character.
```

```
3.403 Text File
A file that contains characters organized into zero or more lines. The lines do not contain NUL characters and none can exceed {LINE_MAX} bytes in length, including the <newline> character. Although POSIX.1-2017 does not distinguish between text files and binary files (see the ISO C standard), many utilities only produce predictable or meaningful output when operating on text files. The standard utilities that have such restrictions always specify "text files" in their STDIN or INPUT FILES sections.
```

となっている。ザクッと訳すと

- 行とは、改行文字を含む0文字以上の文字列である。

- ファイルは、0行以上の文字列で構成される。

と指定されている。

ということで、ファイルの最終行に改行を入れておくことが望ましいということがわかりました。

## エディタで自動で改行を入れる

エディタによっては、ファイルを保存するときに自動で改行を入れてくれる機能があります。

例えば、VSCodeの場合は、設定で`files.insertFinalNewline`を`true`にすることで、ファイルの最終行に改行を入れてくれます。

こういう点で僕みたいにレビューされる工数を少なくするためにも、設定を見直してみましょう。
[React] Reactでの非同期処理について考える

# React での非同期処理

Reactでの非同期処理の歴史

1. コンポーネントのライフサイクルを使用
1. Reduxミドルウェアを使用
1. useEffect Hooks を使用


## コンポーネントのライフサイクルを使用
Reactがリリースされた当初は、`componentDidMount`といったReact のライフサイクルを利用し、非同期処理を実施していました。

```tsx
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hits: [] };
  }
 
  async componentDidMount() {
    const result = await axios(
      'https://hn.algolia.com/api/v1/search?query=redux',
    );
 
    this.setState({ hits: result.data });
  });
 
  return (
    <ul>
      {data.hits.map(item => (
        <li key={item.objectID}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}
```

### :memo: デメリット
- ロジックが追加されるごとに、コンポーネントが肥大化していく

## Redux Middleware 

その後、`Redux`がグローバルな状態管理ライブラリとして普及していくと、データフローの一環として、`Redux`に非同期処理も任せるようになっていきました。

`Redux`には`Middleware`といった機能が搭載されており、`Reducer`の実行前後に任意の処理を追加することができました。

`Middleware` ライブラリとして `Redux Thunk` や `Redux Saga` などが利用されていました。

```tsx
import { Action, Dispatch } from 'redux';
import { ThunkAction } from 'redux-thunk';
import { AppState } from './store';

const initialState = {};

// Reducerの定義
export default function todosReducer(state = initialState, action: Action<string>) {
  switch (action.type) {
    case 'todos/todosLoaded':
      return {
        ...state,
        todos: action.payload
      };
    default:
      return state;
  }
}

// Thunk function
export const fetchTodos = (): ThunkAction<void, AppState, null, Action<string>> => async (dispatch: Dispatch, getState: () => AppState) => {
  try {
    const response = await client.get('/fakeApi/todos');
    dispatch({ type: 'todos/todosLoaded', payload: response.todos });
  } catch (error) {
    console.error('Failed to fetch todos:', error);
  }
}

```

### :memo: デメリット
- 学習コストが高い
- ボイラープレートが多い
- Storeの構造が過度に複雑化
- 使用するミドルウェアでコミュニティが分断される

## useEffect Hooks

React `16.8` から、非同期処理の課題を解決するためのソリューションが公式によって追加されました。
それが `useEffect Hooks` です。

useEffect の中で非同期処理を定義することでコンポーネントの肥大化を防ぐことができるようになりました。

```tsx
import { FC, useEffect, useState } from 'react';

import { requestPath, weatherConditionsMap } from './data';
import { Weather } from './domain/type';

const SampleAsynchronous: FC = () => {
  const [weather, setWeather] = useState<Weather>({} as never);

  useEffect(() => {
    const getTodayWeather = () => {
      fetch(requestPath)
        .then((data) => data.json())
        .then((json) => {
          setWeather((state) => ({
            ...state,
            code: weatherConditionsMap[json.current.weather_code],
            temperature: json.current.temperature_2m,
          }));
        });
    };

    void getTodayWeather();
  }, []);

  return (
    <>
      <h1>Tokyo Weather</h1>
      {weather.code ? (
        <>
          <div>{`現在の東京の天気は${weather.code}です`}</div>
          <div>{`温度: ${weather.temperature}℃`}</div>
        </>
      ) : (
        'data loading...'
      )}
    </>
  );
};

export default SampleAsynchronous;
```

詳細コード: https://github.com/PenPeen/react_practice/pull/43

# まとめ
非同期処理も扱いやすくなっていることがわかりますね...
Databricks Certified Generative AI Engineer Associateに合格しました！

久々の新資格。

![](https://api.accredible.com/v1/frontend/credential_website_embed_image/certificate/106220521)

# Databricks Certified Generative AI Engineer Associateとは

https://www.databricks.com/learn/certification/genai-engineer-associate

[こちら](https://www.databricks.com/jp/blog/databricks-announces-industrys-first-generative-ai-engineer-learning-pathway-and-certification)にあるように今年の1月にスタートした認定資格です。Databricksを用いてLLMを活用したソリューションを設計、実装するスキルを評価します。

# 試験概要

Databricks Certified Generative AI Engineer Associate認定試験では、Databricksを用いてLLMを活用したソリューションを設計、実装する能力を評価します。これいは、複雑な要件を対応可能なタスクにブレークダウンする問題の分解、包括的なソリューションを開発するために、現行の生成AIランドスケープから適切なモデルやツール、アプローチを選択することが含まれます。また、セマンティックな類似検索のためのVector Search、モデルをデプロイするためのモデルサービング、ソリューションライフサイクルを管理するためのMLflow、データガバナンスのためのUnity CatalogのようなDatabricks固有のツールに関しても評価します。この試験に合格した人は、高性能なRAGアプリケーション、Databricksとそのツールセットを完全に活用するLLMチェーンを構築、デプロイできることが期待されます。

この試験では以下をカバーします:

1. Design Applications(アプリケーションの設計) – 14%
1. Data Preparation(データの準備) – 14%
1. Application Development(アプリケーションの開発) – 30%
1. Assembling and Deploying Apps(アプリケーションの組み立てとデプロイ) – 22%
1. Governance(ガバナンス) – 8%
1. Evaluation and Monitoring(評価とモニタリング) – 12%

- **タイプ** 試験官付きの資格試験
- **問題数** 45
- **時間** 90分
- **費用** 200ドル
- **質問形式** 複数選択式
- **試験支援** 許可しない
- **言語** 英語
- **提供方法** オンライン監督
- **前提条件** 無いが関連トレーニングを受けることを強く推奨
- **推奨される経験** 試験ガイドにある生成AIソリューションタスクを実行する6ヶ月以上のハンズオンの経験
- **有効期間** 2年

## 関連トレーニング

- インストラクターによるトレーニング: [Generative AI Engineering With Databricks](https://customer-academy.databricks.com/learn/course/internal/view/classroom/1980/generative-ai-engineering-with-databricks)
- セルフペース(Databricksアカデミーで利用可能): Generative AI Engineering With Databricks

## 試験の準備

- 試験で何が出題されるのかを理解するために[Databricks Certified Generative AI Engineer Associate Guide](https://www.databricks.com/sites/default/files/2024-05/Databricks-Exam-Guide-Generative-AI-Engineer-Associate-Exam-Guide.pdf)を確認する。
- 関連トレーニングを受ける
- 試験に登録
- 技術的要件やシステムチェックを実施
- ギャップを理解するためにサイド試験ガイドを確認する
- ギャップを埋めるために勉強する
- 試験を受ける！

## 登録

[exam delivery platform](http://webassessor.com/databricks)から登録します。

# 所感

[Databricks Certified Generative AI Engineer Associate Guide](https://www.databricks.com/sites/default/files/2024-05/Databricks-Exam-Guide-Generative-AI-Engineer-Associate-Exam-Guide.pdf)を読んでもらえばわかりますように、**絶対に**自分の手でDatabricks上でRAGアプリケーションを構築、デプロイしておいた方がいいです。アソシエイトといえども実装してみないと回答できない問題が結構あります。後半にサンプルの問題があるので雰囲気掴んでいただけるかと。あと、構築の話だけでなく、評価に関する知識も求められます。

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
ローカルLLMのダウンロードとローカル保存、オフライン実行方法まとめ

最近Llama3とかRecurrentGemmaとか次から次へとリリースされて、試してみるだけでも大変ですよね。

この記事はそういったローカルLLMを試すときに、最低限必要となる実行コードをまとめます。

主な実行内容はこちらです。

- LLMのダウンロード
- ダウンロードしたLLMをローカルに保存(キャッシュではない)
- ローカルに保存したLLMを使ってテキスト生成

※ なお、今回対象となるLLMはHuggingfaceに公開されているものとします。

## LLMのダウンロード

```python
# キャッシュの場所を指定したいとき
import os
os.environ['HF_HOME'] = './cache'

# Huggingfaceのトークン認証が必要なとき(Gemmaなど)
import getpass
os.environ['HF_TOKEN'] = getpass.getpass('HF_TOKEN:')

from transformers import AutoTokenizer, AutoModelForCausalLM

# 公開されているモデルの名前
model_name = 'google/gemma-1.1-2b-it'

# トークナイザとモデルの読み込み
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    device_map='cuda',
)
```

## LLMのローカル保存

この方法でローカルに保存しておけば、モデルの公開が終了した場合や更新されてしまった場合などでも固定のモデルを使用し続けることができます。
```python
# model_nameと同じ名前(ディレクトリ名)で保存
tokenizer.save_pretrained(model_name)
model.save_pretrained(model_name)
```

## ローカル保存したLLMを実行

```python
# 今回は公開されているモデルの名前と同じ名前のディレクトリへ格納したため
# model_nameをgoogle/gemma-1.1-2b-itとします
# ちなみにHuggingfaceに公開されているものとローカルにあるもので同じ名前がある場合は
# ローカルの方が優先されてロードされるみたいです
model_name = 'google/gemma-1.1-2b-it'
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    device_map='cuda',
)

# 今回はchat_templateがあるchatモデルであるため、
# tokenizer.apply_chat_templateを使用
chat = [
    {'role': 'user', 'content': '徳川幕府の歴代将軍を表形式で教えてください。'},
]
input_ids = tokenizer.apply_chat_template(chat, tokenize=True, return_tensors='pt').to(model.device)
outputs = model.generate(input_ids, max_new_tokens=1000)
print(tokenizer.decode(outputs[0]))
```

```sh:出力
<bos><start_of_turn>user
徳川幕府の歴代将軍を表形式で教えてください。<end_of_turn>
* 1333年 - 1335年：足利義昭
* 1335年 - 1346年：足利義元
* 1346年 - 1351年：足利義昭
* 1351年 - 1368年：足利義元
* 1368年 - 1374年：足利義昭
* 1374年 - 1380年：足利義元
* 1380年 - 1382年：足利義昭
* 1382年 - 1385年：足利義元
* 1385年 - 1394年：足利義昭<eos>
```
Spark 4.0.0-preview1を動かしてみる

[リリースページ](https://spark.apache.org/news/spark-4.0.0-preview1.html)からSparkをダウンロードして、`spark-shell`を起動します。

```txt:Spark 4.0.0-preview1の起動
$ ./spark-4.0.0-preview1-bin-hadoop3/bin/spark-shell
WARNING: Using incubator modules: jdk.incubator.vector
Using Spark's default log4j profile: org/apache/spark/log4j2-defaults.properties
{"ts":"2024-06-15T06:05:17.601Z","level":"WARN","msg":"Your hostname, tobita-mac-mini.local, resolves to a loopback address: 127.0.0.1; using 192.168.68.108 instead (on interface en1)","context":{"host":"tobita-mac-mini.local","host_port":"127.0.0.1","host_port2":"192.168.68.108","network_if":"en1"},"logger":"Utils"}
{"ts":"2024-06-15T06:05:17.606Z","level":"WARN","msg":"Set SPARK_LOCAL_IP if you need to bind to another address","logger":"Utils"}
{"ts":"2024-06-15T06:05:18.354Z","level":"INFO","msg":"Registering signal handler for INT","logger":"SignalUtils"}
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 4.0.0-preview1
      /_/
         
Using Scala version 2.13.14 (OpenJDK 64-Bit Server VM, Java 21.0.3)
Type in expressions to have them evaluated.
```

![web.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/5adbbc29-454e-9e31-8364-d905e9334fdd.png)

Spark 4系からJava21が利用可能ですが、Web UIにてJava21で動いていることが確認できました 🤩

以下、試しにJava21で導入されたVirtual Threadを動かしてみた結果です。
10万個のFutureの中でスリープしAwaitしていますが、1268msで処理が完了しています。

```scala
scala> import java.util.concurrent.Executors
     | import scala.concurrent.duration.Duration
     | import scala.concurrent.{Await, ExecutionContext, Future}
     | 
     | implicit val ec: ExecutionContext = ExecutionContext.fromExecutor(Executors.newVirtualThreadPerTaskExecutor())
     | 
     | val start = System.currentTimeMillis()
     | val futures = (1 to 100000).map { _ =>
     |   Future{
     |     Thread.sleep(1000)
     |   }
     | }
     | 
     | Await.ready(Future.sequence(futures), Duration.Inf)
     | 
     | val end = System.currentTimeMillis()
     | println(s"${end - start}ms")
1268ms
```
curlでいろんな結果を見るならwオプションが便利だった

APIサーバーの開発をして簡単にレスポンスタイムなど性能を見たいありますよね。

毎回k6などでテストをするのも面倒だし、curlで簡単に見れないかなーと思って調べたところ、wオプションが便利だったのでメモしておきます。

## 結論

--write-out(-w)でtime_totalを表示すると、リクエストにかかった時間がわかります。

```bash
curl --request GET \
 -w"time_total: %{time_total}\n" \
 --url ＄URL
```

## write-outオプション

`-w`オプションを使うことで、curlの出力をカスタマイズできます。

サンプルとして`-w '%{response_code}\n' $URL`とすると、レスポンスコードが表示されます。


## よく使うフィールド

| フィールド | 説明 |
| ---- | ---- |
| %{http_code} | レスポンスコード |
| %{time_connect} | 接続にかかった時間 |
| %{time_appconnect} | アプリケーションに接続するのにかかった時間 |
| %{time_pretransfer} | リクエストが開始されてから最初のバイトが転送されるまでの時間 |
| %{time_starttransfer} | リクエストが開始されてから最初のバイトが転送されるまでの時間 |
| %{time_total} | リクエストにかかった合計時間 |


```bash

curl --request GET \
 -w"http_code: %{http_code}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" \
 --url $URL
```


参考:
https://github.com/curl/curl/blob/aab0c16990ff4cccbb68ab9fa9c81823b288fdcc/docs/cmdline-opts/write-out.md?plain=1#L4

https://qiita.com/yasushi-jp/items/bcc67b76d2491a1bc09e
（こちらの記事を参考にしてお仕事が進みました。ありがとうございました。）
Excel VBA 配列練習

### セル範囲を配列に格納してコピーペーストする

Copy メソッドを使えばできるので、配列にする必要はありませんが、配列の練習として書きました。

```vb
Dim arr() As Variant
  
ReDim arr(Range("A4").CurrentRegion.Count - 1) As Variant
```
変数arr を Variant型で宣言
ReDim で配列変数 arrの要素数を動的に割り当て（格納したい値が入っているセル範囲をCurrentRegionで取得し、Count - 1 で最終行を取得、配列の要素は0から始まるため - 1 で部屋の数（要素数）を調整、- 1 がないと1多くなる）

```vb
Dim i As Long
Dim j As Long
  
  For Each x In Range("A4").CurrentRegion
  
    arr(i) = x.Value
    
    i = i + 1
    
  Next x
```
セル範囲 Range("A4").CurrentRegion を For Eachで配列変数arr に1つずつ格納

```vb
  For j = LBound(arr) To UBound(arr)
  
    Cells(j + 4, 2) = arr(j)
    
  Next j
```
arrの中身をFor next で隣の列にコピー


```vb
Sub CopyByArray()

  Dim arr() As Variant
  
  ReDim arr(Range("A4").CurrentRegion.Count - 1) As Variant
  
  Dim i As Long
  Dim j As Long
  
  For Each x In Range("A4").CurrentRegion
  
    arr(i) = x.Value
    
    i = i + 1
    
  Next x
  
  For j = LBound(arr) To UBound(arr)
  
    Cells(j + 4, 2) = arr(j)
    
  Next j
  
End Sub
```
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/f5e21abd-5ba4-6398-635b-27cd6d971190.png)


A列4行目から値が入っていれば、何行目まで入っていても同じコードですべてコピーできます。
【AWS】S3バケットのファイル作成をトリガーにLambdaを実行する

# はじめに
AWSのS3バケットにファイルをアップロードすることをトリガーにしてLambda関数を実行する方法について勉強したので備忘録も兼ねて本記事にまとめています。本記事では、S3バケットとLambda関数の設定手順、およびトリガーの設定方法を記載する。


# 環境
python 3.12


# S3側の準備
Lambdaから指定するバケットを作成します。

2. Amazon S3 > バケット > バケットを作成 を選択。
2. 任意のバケット名を入力し、右下のバケットを作成をクリック。（本記事ではバケット名を`test-lambda-trigger1`とします。）


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/1114e61d-a0a7-e475-bae8-e1572d123795.png)



# Lambda側の準備

## 関数の作成
1. Lambda > 関数 > 関数の作成 から新規でLambdaを作成します。
2. 任意の関数名を入力し、右下の関数の作成をクリック。（本記事では関数名を`test-s3-lambda`とします。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/15519b94-fa7b-2779-87f7-9333a1ca9362.png)

## トリガーの設定

1. 設定タブ > トリガー > トリガーの追加から選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/25655d8a-85b4-fd58-cc20-392f35709e29.png)

 
２. 先ほど作成したバケット名（`test-lambda-trigger1`）と入力し`再帰呼び出し`の項目にチェックを入れ右下の`追加`ボタンをクリック。
S3のバケット内にフォルダを作成している場合は、任意のフォルダパスを`プレフィックス`に記載する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/c4058024-bbd7-e32c-aaa5-08cfbd8ee6c5.png)

:::note warn
トリガーを設定する際に、同一のバケットで条件が同じものをトリガーにすることはできないので注意する。
既存のLambdaで同じバケットのトリガー条件がある上で、新規のLambdaで同じバケット、トリガーを指定しようとするとエラーが発生します。

> trigger の作成中にエラー が発生しました: Configurations overlap. Configurations on the same bucket cannot share a common event type.


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/8d0ada83-2265-aa77-b460-5fdf73cc8962.png)


:::



## ソース
```python:lambda_function.py
def lambda_handler(event, context):
    print('Hello Lambda')
    return 
```


# 実行 & 結果確認
任意のファイルをS3にアップロードし、Lambdaが実行されたか動作を確認する。
バケットにファイルをアップロード後、CloudWatchのログを確認すると、Hello Lambdaのログが出ていることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/7ad89019-5302-1725-6582-b7466d3a2669.png)
DistrolessというDockerイメージがよさげ

Googleが提供しているDockerイメージの一つにDistrolessというものがある。

GitHubリンクは[こちら](https://github.com/GoogleContainerTools/distroless)

本記事ではこのイメージの特徴と簡単な利用方法について説明する。

## 一般的なDockerイメージ

例えば、DebianやUbuntuなどのOSイメージを使う場合、OSに関連するパッケージやツールが含まれています

しかし実際にアプリケーションを商用利用する場合、これらのパッケージやツールは不要であることが多く、不要なパッケージやツールが含まれています。

利用しないパッケージやツールが含まれていることで生じる問題は以下の通りです。

- セキュリティリスク
- イメージサイズの増加
- メンテナンスの複雑化

以上から、アプリケーションの実行に必要な最低限のコンポーネントのみを含むDockerイメージがあると便利です。

## Distrolessの特徴

一方で、Distrolessはアプリケーションの実行に必要な最低限のコンポーネントのみを含むDockerイメージです。

上記で記載した内容の裏返しにはなりますが、Distrolessの特徴は以下の通りです。

- OSに関連するパッケージやツールが含まれていない
- イメージサイズが小さい
- セキュリティリスクが低い

これにより、アプリケーションの実行に必要な最低限のコンポーネントのみを含むDockerイメージを利用することで、セキュリティリスクを低減し、イメージサイズを小さくすることができます。

これを商用環境には特に有用です。

## Distrolessの利用方法

筆者がこのDockerイメージを推す理由はただひとつ。

**GoでビルドしたバイナリをDockerイメージに含めるだけで、実行環境を構築できるから**です。

Goは静的バイナリを生成することができるため、DistrolessのDockerイメージに含めるだけで実行環境を構築が可能です。

CPUアーキテクチャの差に気をつけてビルドする必要がありますが、上記のメリットを享受できるためGoでアプリケーションを開発する際には本番環境にDistrolessのDockerイメージを利用することを個人的にはおすすめします。

## 簡単に試してみる

簡単にDockerfileを作ってみます。

今回は単純にホストマシン上のテキストファイルをコピーしてビルドするだけのDockerfileを作成します。

```Dockerfile
# Distroless Static Dockerfile
FROM gcr.io/distroless/static:nonroot

#  Copy an text file
COPY sample.txt /sample.txt
```

sample.txtは以下の内容です。

```txt
Hello from distroless container
```

このイメージをビルドしてみます。

```sh
% distroless % docker build -t test-distroless .

~~~

% docker images
REPOSITORY                   TAG                            IMAGE ID       CREATED         SIZE
test-distroless              latest                         xxxxxxxxxxxx   2 minutes ago   1.99MB
```

イメージサイズが1.99MBと非常に小さくなっていることが確認できます。

さて、このコンテナでcatコマンドを実行してみようとします。

```sh
% docker run --rm test-distroless cat /sample.txt

docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "cat": executable file not found in $PATH: unknown.
```

このように、DistrolessのDockerイメージにはcatコマンドなどのシェルが含まれていないため、コンテナ内でシェルを実行することができません。

ここでGoでビルドしたバイナリをDistrolessのDockerイメージに含めることでコマンドを実行することができます。

```go
package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	cat("/sample.txt")
}

func cat(filePath string) {
	file, err := os.ReadFile(filePath)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(file))
}
```

このコードをビルドしてDockerfileに含めることで、DistrolessのDockerイメージに含めることができます。

```Dockerfile
# Distroless Static Dockerfile
FROM gcr.io/distroless/static

#  Copy an text file
COPY sample.txt /sample.txt

#  Run the application
COPY main /main
```

```sh
% distroless % go build -o main main.go
% distroless % docker build -t test-distroless .

~~~

% docker run --rm test-distroless
Hello from distroless container
```

このように、GoでビルドしたバイナリをDistrolessのDockerイメージに含めることで、コンテナ内でコマンドを実行することができることが確認できます。
Python3でファイルのメッセージダイジェストを求めたい

Python3でファイルのメッセージダイジェストを求める方法を紹介します。ここではSHA256を例にします。

python3.11以降の場合、`hashlib.file_digest`を利用します。

```python3
import hashlib
with open('INPUT.txt', 'rb') as f:
    digest = hashlib.file_digest(f, "sha256")
print(digest.hexdigest())
#=> 6f67ea379608add8b4f3c0a3c95c0e70ab2752405de7c69c152faabd5870305e
```

それ以前のバージョンの場合は、ファイルを自前で読み込む必要があります。

まずファイル内容をすべてメモリ上に展開してよい場合は以下のようなコードになります。

```python3
import hashlib
with open('INPUT.txt', 'rb') as f:
    digest = hashlib.sha256(f.read())
print(digest.hexdigest())
#=> 6f67ea379608add8b4f3c0a3c95c0e70ab2752405de7c69c152faabd5870305e
```

ファイルを少しずつ読み込みながら、メッセージダイジェストを求めることも可能です。

```python3
import hashlib
digest = hashlib.sha256()
with open('INPUT.txt', 'rb') as f:
    while b := f.read(1024):
        digest.update(b)
print(digest.hexdigest())
#=> 6f67ea379608add8b4f3c0a3c95c0e70ab2752405de7c69c152faabd5870305e
```

**環境情報**

```
docker run -it --rm -v .:/work -w /work python:3.12 python3 main.py
```
CloudFlareにデプロイするためのRemixプロジェクトでテーブルの要素を絞り込んで表示してみる

## 概要

下記の記事でテーブルに入っているすべての要素を一覧的に表示する実装をしてみた。
今回は何かしらの条件をつけて絞り込んで表示してみようと思う。

https://qiita.com/miriwo/items/93ab3d71d0987edea2eb

## 前提

下記の内容が完了していること。

https://qiita.com/miriwo/items/93ab3d71d0987edea2eb

## 方法

今回の内容はPrismaのドキュメントで言うところのこちらを使いそう。

https://www.prisma.io/docs/orm/prisma-client/queries/crud#get-the-first-record-that-matches-a-specific-criteria

取り急ぎ今回は「tasksテーブルのdeleted_atがnullのものだけ一覧に表示する」ようにデータ取得部分を変えてみようと思う。

1. 前回作成した`app/routes/tasks-loader.ts`を下記のように修正

    ```app/routes/tasks-loader.ts
    import type { LoaderFunctionArgs} from "@remix-run/cloudflare";
    
    export const loader = async ({ context }: LoaderFunctionArgs) => {
      try {
        return await context.db.tasks.findMany({
          where: { deleted_at: null },
        });
      } catch (error) {
        console.error("Failed to load tasks:", error);
        throw new Response("Internal Server Error", { status: 500 });
      }
    }
    ```

1. `npm run dev`を実行後`/tasks`を確認し、idが4と8と12のdeleted_atにnull以外が入っているものが表示されていなければ作業は完了

    ![CleanShot 2024-06-15 at 14.43.04@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/4e43f899-0607-6455-af95-31442382e516.png)


## 参考文献

https://www.prisma.io/docs/orm/prisma-client/queries/crud
【備忘録】ciscoスイッチの勉強

# コマンド

```
enable
```
とうつと、特権モードに入れる。プロンプトが`#`になり,いろいろなコマンドが打てるようになる。

## コンフィグの確認
```
show run
```
`show running-config`である。実行することで現在設定されているコンフィグを確認できることが可能。moreと書いてある場合、カーソル下か、スペースキーで進めていける。

## スイッチにIPアドレスをいれる。

コンフィグモードに移行する。
```
conf　t
```
`configure terminal`の略

- コンフィグモードは機器全体の設定項目
    - デフォゲートなど。
    - ホスト名など
- インターフェースモード
    - インターフェースのIPなど。

```
hostname SW1
```
とあると、ホスト名を変更できる。

次に、インターフェースにIPをつける。
```
int vlan 1
ip address 10.1.1.200 255.255.255.0
no shut
```

- `interface vlan1`
- 設定したいアドレスと、サブネットマスク
- `no shut` デフォルトでは、スイッチの設定するIPは無効化される。`no shut`で、これを有効化している。
設定すると、`changed state to up`となる。

![IMG_5488.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/4da9a6ef-bba0-aa21-db1f-6643d02d035d.jpeg)


また、コンフィグモード、特権モード、ユーザモードに戻る場合は、`exit`を選択する。

この時、ためしにPC1からpingを実行すると、1回失敗した後に通信が届く。
この時に1回失敗しているのは、ARPテーブルがまだできていないから。

IPとMACアドレスを対応付けているプロトコルがARP.
そして、この時どのような通信されているかというと、、
1. ARPリクエストをブロードキャストして、対象のIPもMACアドレスに問い合わせる
2. そのIPを持つホストのARPレスポンスを実行する。
2. 解決したIPとMACアドレスの対応表を、ARPテーブルに更新させる。

## インターフェースの呼び方

- First Ethernet
    - 最大の転送速度が100Mbps
- Gigabit Ethernet
    - 最大の転送速度が1GBps
- Console
    - 機器に直接刺して操作することができるポート。
    - TeraTermを使用したりする。コンソール側はRJ45という、LANケーブルと同じポート。で、それの内容をUSBに変換して操作するパソコンに転送できる。 


## VTY接続

VTY接続と、IPアドレスの設定があると、インターネット先からでも接続できる。
それを試してみよう。
スイッチ側で以下のコマンドを実行する。
```
en
conf t
line vty 0 4
password sample
login
end
```
- line vty 0 4は、`0~4`の、5回線が使えるということ。
- apsswordは小文字、大文字も区別される
- endで、一度で特権モードまで戻れる

`show run`した後にスペースで下に行くと、vtyのパスが確認できる。
そして、LAN内のPCから、
```
telnet 設定したIP
設定したパスワード
```
を入れることで、接続することができる。ただし、この場合だと特権モードに入れない。

スイッチ側で以下のコマンドを実行
```
conf t
enable password sample
```
- これにより、今後enableを打つと、パスワードを聞かれるようになる。

そして、再度telnetしたPCから特権モードに入ることができる。


### shutダウンをした時。

スイッチをシャットダウンした際、`no shut`を入れ忘れていた場合、起動したら`shut down`になってしまう。この時、再度no shutを入れることで戻すこともできる。
コンサル一年目が学ぶこと

# 目的
備忘録として記載する

## 第1章　コンサル流話す技術
- 結論から話す
    - PREP法
        1. Point
        1. Reason
        1. Example
        1. Point (繰り返し)
- 相手に理解してもらうように話す
    - 無言、資料をずっと見ている、話者を見ない、曖昧な返事→理解できていないサイン
 
## 第2章　コンサル流思考術
- 「考え方を考える」という考え方
    - 大きな設計図を示し、作業手順の合意を取る
    - 手順に基づいて、細かい作業を進める
- ロジックツリーを使いこなす
- 仮説思考
    1. 予想できる範囲でストーリーラインを描く
    1. ストーリーラインに沿って、リサーチポイントを絞る
    1. 仮説に対する検証として、リサーチを行う

## 第3章　コンサル流デスクワーク術
- 文書作成の基本、議事録書きをマスターする
    1. 日時、場所
    1. 参加者
    1. agenda
    1. 決まったこと
    1. 決まらなかったこと
    1. 確認事項
    1. ToDo
- 課題管理表
    1. No.
    1. 課題
    1. 課題の詳細
    1. 期限
    1. 対応方針
    1. 対応結果
    1. ステータス
    1. 担当者

## 第4章　コンサル流ビジネスマインド
[ExcelVBA]ユーザーフォーム・テキストボックスを使ってセルにテキストを入力する方法

1.プロジェクトエクスプローラーに新規ユーザーフォームを追加する
VBE上にて、挿入→ユーザーフォーム、を選択
（ここでは、作成したユーザーフォームのオブジェクト名を「frm_テキスト入力」とする）

2.ユーザーフォーム上の任意の位置に、テキストボックス、コマンドボタンを配置する
VBE上にて表示→ツールボックスを選択することにより、各種コントロールが選択できる
（ここでは、テキストボックスのオブジェクト名を「TextBox」、コマンドボタンのオブジェクト名を「CommandButton」とする）

3.ユーザーフォームにイベントマクロのコードを記述する
ユーザーフォームの任意の位置で右クリック→コードの表示、を選択することにより、コード入力画面に切り替えることが出来る
~~~VBA
Option Explicit

'CommandButtonがクリックされた時に実行するイベントマクロ
Private Sub CommandButton_Click()
    
    '入力されたテキストの出力先セルを指定する
    Dim outputCell As Range: Set outputCell = ThisWorkbook.Worksheets(1).Range("A1")
    
    'Me(frm_テキスト入力).TextBox.Textプロパティにて、テキストボックスに入力されたテキストを取得し、それを出力先セルに代入する
    outputCell.Value = Me.TextBox.Text
    
End Sub
~~~

4.ブックが開かれた際に自動でユーザーフォームが表示されるよう、Workbookモジュール上にイベントマクロを記述する
~~~VBA
Option Explicit

'ブックが開かれた際に実行されるイベントマクロ
Private Sub Workbook_Open()

    'ユーザーフォームを表示する
    frm_テキスト入力.Show

End Sub
~~~

![ユーザーフォーム・テキストボックス.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816680/24b485fd-e6b5-f6b3-5038-e90680f1766e.png)
闘魂Elixir ーー AtCoder Beginner Contest 347(B)をElixirで楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>


# はじめに

[AtCoder Beginner Contest 347](https://atcoder.jp/contests/abc347)を[Elixir](https://elixir-lang.org/)で解いてみます。

[AtCoder](https://atcoder.jp/)を解くのが趣味で、休憩時間に解いているという若い人がいて、それってすごい意識の高い休憩時間の過ごし方だと思って、私も真似してみることにしました。


# [AtCoderをElixirでやってみる](https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01)

入力の読み取り方や解答の作り方は、別の記事にまとめています。


https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01

ご参照くださいませ。

[Elixir](https://elixir-lang.org/)で[AtCoder](https://atcoder.jp/)を楽しむためには、エントリポイントを`Main.main/0`にする必要があります。つまり`Main`モジュールを作って、その中に`main/0`関数を定義するわけです。

# [B - Substring](https://atcoder.jp/contests/abc347/tasks/abc347_b)

問題はリンク先をご参照くださいませ。
私の解答を貼っておきます。


<details><summary>私の解答</summary>

_問題文を読んでいることを前提にひとこと解説をしておきます。_

文字列を部分文字列に切り出して、重複するものは省く必要があります。
骨格では[String.slice/3](https://hexdocs.pm/elixir/String.html#slice/3)関数で、先頭位置と長さを指定します。
[for](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#for/1)を使って、先頭位置と長さを順に指定します。[:reduce](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#for/1-the-reduce-option)で[MapSet](https://hexdocs.pm/elixir/MapSet.html)を指定しておくことにより、切り出した文字列のうち重複するものを除去します。
できあがった[MapSet](https://hexdocs.pm/elixir/MapSet.html)データの長さを[Enum.count/1](https://hexdocs.pm/elixir/Enum.html#count/1)関数で測って完成です。


```elixir
defmodule Main do
  def main do
    s = IO.read(:line) |> String.trim()
      
    solve(s)
    |> IO.puts()
  end
  
  def solve(s) do
    len = String.length(s)
    
    substrings = for start <- 0..(len - 1), length <- 1..(len - start), into: MapSet.new() do
      String.slice(s, start, length)
    end
    
    Enum.count(substrings)
  end
end
```




</details>




---

# さいごに

[AtCoder Beginner Contest 347](https://atcoder.jp/contests/abc347)を[Elixir](https://elixir-lang.org/)で解くことを楽しみました。

あなたのお好きなプログラミング言語でお楽しみください。

---


**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
コマンドラインでnohupしながらforループしたい

# はじめに

コマンドラインで（簡単に）forループを回したい、ということはよくあることかと思います。一方、（コマンド自体は単純であったとしても）ループなのですから（回数によってはものすごく）時間が掛かる可能性があり、（接続が切れたりして）端末が終了してしまってもnohupで処理は続けてほしいな、というのも人情でしょう。forもnohupもそれぞれ単体は難しいものではないですが、組み合わせて使うのにちょっと苦戦しました[^scriptfile]ので、その時の記録です。あと、シェルはbashです。

また、恒例のお断りですが、この文章の内容は、筆者が所属している会社・団体とは一切関わりがありません。いわゆる「自主的な研究の成果の発表」というものです。

[^scriptfile]: コマンドラインにこだわらず、スクリプトファイル書けばよかったのでは、と言われればその通りです。

# for
たとえば10回繰り返すには以下のようにします。この辺りは皆さんご存じでしょう。
~~~
$ for i in {1..10}; do echo $i; done
1
2
3
4
5
6
7
8
9
10
~~~
# nohup
端末が終了してもa.outに動いておいてもらいたい場合には以下のようにするでしょう。これももちろん皆さんよくご存じですね。
~~~
nohup ./a.out > output
~~~
# 組み合わせ
だがしかし、nohupとforを単純に組み合わせると以下のように上手く行きません。
~~~
$ nohup for i in {1..10}; do ./a.out; done > output
-bash: syntax error near unexpected token `do'
~~~
以下のようにすると、上手く行きます。
~~~
nohup bash -c 'for i in {1..10}; do ./a.out; done' > output
~~~
bashのmanを読んでもどうして上手く行ったかはよく分かりませんでした。''で囲まれた部分はまとまりなのなのだから[単体のfor](#for)の時のように処理してね、そのまとまりを処理するbashに対してのnohupだよ（forに対して直接ではないよ）、ということで上手く行っているのかな、と考えています。（合ってるかな。）

# おわりに
forではなくwhileだったら同様の回避法に触れた[記事](https://qiita.com/blueskyarea/items/d785b696bef56a9760d9)がありました。またやってしまいました、車輪の再発明、、、orz
いや、whileではなくforなので厳密では再発明ではない！？（まあ、分かっている人にとっては再発明ですよねぇ。）
GHA: ビルドと資産の取得

# 導入
こんにちは。エンジニアのYamaです。
前職ではデプロイする資産をリリースする前に社内サーバーのストレージに格納することがルールとなっていました。
元々ソースコードがバージョン管理されておらず、資産も各自のローカルPC内の環境でビルドしていました。
そのため、その資産を保存しておくルールがありました。
私が離職する前にはGitHubでソースを管理し、リリースごとにタグを切る運用にしていていましたが、そのルールが撤廃されることはありませんでした。

ただ、少なくとも各自の環境でビルドしていること自体、不要な差分が出てしまう原因でもありましたので、GitHub Actions上で、ビルドを実行することにしました。

# GitHub Actions

## 中身

主にSpring bootのプロジェクトが多かったので、今回は`mvn package`で資産を作成する際のGHAになります。

```yaml:build.yaml
name: Build hogehoge
on:
  push:
    branches:
      - master
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      targetwar: ${{ steps.builder.outputs.targetwar }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: 'corretto'
          java-version: '11'
      - name: building
        id: builder
        run: |
          mvn package
          TARGET_WAR=$(ls ./target/hogehoge.war)
          echo "targetwar=${TARGET_WAR}" >> "$GITHUB_OUTPUT"
      - uses: actions/upload-artifact@v4
        with:
          name: target-war
          path: ${{ steps.builder.outputs.targetwar }}
```

## 簡単な解説

### 実行タイミング

上記ソースのこの部分が実行タイミングになります。
```yaml
on:
  push:
    branches:
      - master
```
このGHAが実行されるのは、`master`ブランチにプッシュされたタイミングになります。
私が担当していたプロジェクトは大抵`master`ブランチを本番リリース用のブランチとして利用していました。

### ワーカー
ワーカーはyamlに記載の通り`ubuntu-latest`としました。

### 各ステップ
#### actions/checkout@v4
ここで、ソースをチェックアウトしてきています。

#### actions/setup-java@v4
Javaのバージョンの設定等をしています。

#### building
Mavenコマンドを実行し、Warファイルを作成しています。
作成したファイル名を取得するようにしています。

#### actions/upload-artifact@v4
`building`ステップで作成したWarをGithub上にアップロードしています。

# アップロードされた資産

アップロードされた資産はGithub上からダウンロードが可能です。
以下の画像のようにダウンロードすることができます。

![アップロード資産.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1655179/ca0fe6d1-1141-ceb1-d751-0adeb0930ad8.png)


# 最後に

今回はGitHub Actionsでリリース資産を作成して、GitHub上からダウンロードする方法を紹介しました。
自動でビルドできるのは本当に助かりますね。
ぜひ参考にしてみてください。
ジュニアエンジニア備忘録：アルゴリズム(2) - バブルソート

アルゴリズムの中には様々な整列方法がありますよね。
その中で今回はよく聞くけど、実際に使われているのはあまり見ない「バブルソート」についてまとめてみました。

## バブルソートとは？
### 自分の言葉で整理してみる
配列中で連続した2つの要素を比較し、交代し続けること

### 定義
wikipediaさんによる定義は以下のようです。
>バブルソート（英: bubble sort）は、隣り合う要素の大小を比較しながら整列させるソートアルゴリズム。

https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%96%E3%83%AB%E3%82%BD%E3%83%BC%E3%83%88

## バブルソートの動き
「隣り合う要素の大小を比較」を繰り返すことで整列をしています。
その過程の中で毎回「最大値を最終indexまでに持っていく」をすることになっていますね。

以下のサイトから可視化されたバブルソートのみることができたので、持ってきました。

https://visualgo.net/en/sorting

今回用いるデータはこれ。`[29, 10, 14, 37, 14]`です。

![スクリーンショット 2024-06-15 13.10.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/984c0ca9-c41c-8d63-3c11-e2cf8b0ad756.png)

イテレーション１
![ダウンロード (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/0be497cd-3176-df7d-5378-cfc6b9fd86d1.gif)
イテレーション２
![ダウンロード (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/1be27541-adbe-0ffc-7662-0993084e3eb7.gif)
イテレーション３
![ダウンロード (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/cb729827-5d2f-cd75-7094-87388ca6ca90.gif)

## 実装
### まずは自分で

```myBubbleSort.js
let array = [29, 10, 14, 37, 14];
let num = 1;

while (true) {
    let isSwapped = false;
    for (let i = 0; i < array.length - num; i++) {
        if (array[i] > array[i + 1]) {
            [array[i], array[i + 1]] = [array[i + 1], array[i]];
            isSwapped = true;
        }
    }
    if (!isSwapped) {
        break;
    }
    num ++;
}

console.log(array);
```
通った！

![スクリーンショット 2024-06-15 13.54.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/f0738360-e80b-e1a9-79f9-ec4419198843.png)

工夫したところ
1. モダンなJSで
2. 早期終了ができるように`isSwapped`を設定

先にビジュアルの挙動が見られたため、2番の工夫にたどり着くことができました。
ビジュアル化最高。

### 正解のコード
こちらはUdemyで受けている講義の正解例です。
概ね似ていますね。
しかし、while (true)だとソートされている配列の中は無限に回ってしまうところがクリティカル...😅

```js
function bubbleSort(arr) {
    var noSwaps;
    for (var i = arr.length; i > 0; i--) {
        noSwaps = true;
        for (var j = 0; j < i - 1; j++) {
            console.log(arr, arr[j], arr[j+1]);
            if (arr[j] > arr[j+1]) {
                var temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
                noSwaps = false;
            }
        }
        if (noSwaps) break;
    }
    return arr;
}
```
### 修正すると...
```myBubbleSort.js
let array = [29, 10, 14, 37, 14];

for (let num = 1; num < array.length; num++) {
    let isSwapped = false;
    for (let i = 0; i < array.length - num; i++) {
        if (array[i] > array[i + 1]) {
            [array[i], array[i + 1]] = [array[i + 1], array[i]];
            isSwapped = true;
        }
    }
    if (!isSwapped) break;
}

console.log(array);
```
## 時間計算量
二重ループなので、`O(n^2)`になりそうですね。
しかし、早期終了ができる場合、ベストはO(n)になりますかね？

## 終わりに
書いてみて、効率のいいソートではないと感じました。
配列の中身を全部見に行くため、ある程度ソートされている場合は他のソートを使うべきですね。

## 参考
この記事の内容は主に以下のUdemy講義を元にしています。

https://www.udemy.com/course/js-algorithms-and-data-structures-masterclass/
[Rails] rails db:migrateが失敗したら、スキーマファイルからデータベースを構築しよう

# 概要
マイグレーションに不整合がある場合、**`rails db:migrate`** が失敗することがあります。
過去のmigrationファイルから原因を特定し、修正しようとするとかなり時間がかかります。

このような時は **`rails db:schema:load`** コマンドを使うことで、スキーマファイルから迅速にデータベースを構築することができます。

# マイグレーションコマンド
**`rails db:migrate`:**
db/migrate のマイグレーションファイルを順次実行する

**`rails db:schema:load`:**
db/schema.rbのスキーマ情報をそのままデータベースに反映する ※db/migrate のマイグレーションファイルは使わない

# まとめ
既存プロジェクトの環境構築などで、マイグレーションが失敗した時のために頭の片隅に置いておくと役立つ時が来るかもしれません...

新規メンバー参画予定のため備忘録として執筆... :memo:
毎日ABC day19【c++】ABC327 A-C問題解説【ACコード付き】

# AtCoder Beginner Contest 327

https://atcoder.jp/contests/abc327

## A - ab
```cpp
int main()
{
	int N;
	cin >> N;
	string S;
	cin >> S;
	for (int i = 1; i < N; i++)
	{
		if (S[i] == 'a' && S[i - 1] == 'b')
		{
			cout << "Yes" << endl;
			return 0;
		}
		if (S[i] == 'b' && S[i - 1] == 'a')
		{
			cout << "Yes" << endl;
			return 0;
		}
	}
	cout << "No" << endl;
	return 0;
}
```
## B - A^A
与えられる$10^{18}$までの整数 $B$ と一致するような$A^A$ が 存在するか調べろ、という問題。

$10^{18}$までという制約なので、$A$ の範囲が16までであることに目をつけて、計算量を抑える。
```cpp
int main()
{
	long long  B;
	cin >> B;
	for (int i = 1; i <= 17; i++)
	{
		long long tmp = 1;
		for (int j = 1; j <= i; j++)
		{
			tmp *= i;
		}
		if (tmp == B)
		{
			cout << i << endl;
			return 0;
		}
	}
	cout << -1 << endl;
	return 0;
}
```
## C - Number Place
ナンプレ。0から9までの数字が、①縦でも②横でも③3×3のマスでも重複しないような盤面かどうかを判定せよ、という問題。

①②③それぞれで0から9の数字に対応するbool型を保持し、重複が来たら即座に"No"を出力するというプログラムを書いた。

```cpp
int main()
{
	int A[10][10];
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++) cin >> A[i][j];
	}
	// 重複チェック
	bool check_row[10][10];
	bool check_column[10][10];
	bool check_box[10][10];
	for (int i = 0; i <= 9; i++)
	{
		for (int j = 0; j <= 9; j++)
		{
			check_column[i][j] = false;
			check_row[i][j] = false;
			check_box[i][j] = false;
		}
	}
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			int num = A[i][j];
			int k = (i / 3) * 3 + (j / 3);
			if (check_column[i][num] || check_row[j][num] || check_box[k][num])
			{
				cout << "No" << endl;
				return 0;
			}
			check_column[i][num]= true;
			check_row[j][num] = true;
			check_box[k][num] = true;
		}
	}
	cout << "Yes" << endl;
	return 0;
}
```
【Swift】 JSONEncoder / JSONDecorder の基本的な使い方

サンプルから。

```swift
struct GroceryProduct: Codable {
  var name: String
  var points: Int
  var description: String?
}

let pear = GroceryProduct(name: "Pear", points: 250, description: "A ripe pear.")

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

let data = try encoder.encode(pear)
print(String(data: data, encoding: .utf8)!)

/*
{
  "name" : "Pear",
  "points" : 250,
  "description" : "A ripe pear."
}
*/
```

```swift
struct GroceryProduct: Codable {
  var name: String
  var points: Int
  var description: String?
}

let json = """
{
    "name": "Durian",
    "points": 600,
    "description": "A fruit with a distinctive scent."
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let product = try decoder.decode(GroceryProduct.self, from: json)

print(product.name) 

// Prints "Durian"
```

要するにこういうことです。

![sc 2024-06-15 at 13.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588914/6f384cfa-e06e-68c1-76c7-0fa49386d460.png)

# 🤔 参考
https://x.com/maochanz/status/1801903647279944136

https://android.benigumo.com/20240615/json-encode-decode/
【環境構築】venv

# 導入経緯

Deep Learningの学習環境を用意したく, Pythonに標準搭載されたvenv環境を構築しました.
導入手順はものすごく簡単で, 特に解説の必要もないかと思いますが, 備忘録として一応まとめています.
ご指摘等ありましたら, コメントをお願いいたします.

# 目次

- [動作環境](#動作環境)
- [導入手順](#導入手順)
  - [1. Pythonの導入](#1-pythonの導入)
  - [2. venvの導入](#2-venvの導入)
  - [3. パッケージのインストール](#3-パッケージのインストール)

# 動作環境

私がnenvを導入した際の環境です.

|  |  |
| --- | --- |
| チップ | Apple M3 |
| OS | macOS Sonoma 14.4.1 |
| シェル | zsh |
| ターミナル | iTerm2 |
| パッケージマネージャ | Homebrew |
| Python | 3.9.6 |

# 導入手順

## 1. Pythonの導入

まず初めに, pythonがインストールされているかを確認します.

```zsh:Terminal
python3 --version
```

- インストールされている場合
  以下のバージョン情報が表示されます.

  ```zsh:Terminal
  Python 3.X.X
  ```
  <br>

- インストールされていない場合
  以下のエラーが表示されます.

  ```zsh:Terminal
  zsh: command not found: python3
  ```

  まずは次のコマンドで, インストールできるバージョン一覧を取得します.

  ```zsh:Terminal
  brew search python@3
  ```

  お好きなバージョンを選択し, インストールします.
  本記事では`python@3.9`を扱います.

  ```zsh:Terminal
  brew install python@3.9
  ```

  再度バージョン情報を取得し, エラーがなければPythonのインストールは完了です.

## 2. venvの導入

まずはプロジェクトのルートディレクトリを設定します.

```zsh:Terminal
# sampleディレクトリの作成
mkdir sample

# sampleディレクトリに移動
cd sample
```

続いてsampleディレクトリ内にvenvを作成します.

```zsh:Terminal
python3 -m venv .venv
```

:::note info
`.venv`部分は任意の環境名です. お好きな名前を設定してください.
:::

仮想環境の作成自体は以上で完了です. 簡単ですね.

では続いて, 仮想環境の起動, 停止について解説していきます.

### 2-1. 仮想環境の起動

以下のコマンドで起動できます.

```zsh:Terminal
source .venv/bin/activate
```

### 2-2. 仮想環境の停止

以下のコマンドで起動できます.

```zsh:Terminal
deactivate
```

## 3. パッケージのインストール

venvにパッケージをインストールしていきます.
ここではPythonのパッケージ管理システムである`pip`を使用します.

まずは, `sample`ディレクトリ内に`requirement.txt`を作成します.

```zsh:Terminal
touch requirement.txt
```

:::note info
ディレクトリ構造が以下のようになっていることを確認してください.
```
sample
├─ .venv
└─ requirement.txt
```
:::

ここでは例として`numpy`と`pandas`をインストールします.
`requirement.txt`に以下を記述してください.

```txt:requirement.txt
numpy==1.21.0
pandas==1.3.0
```

これらを次のコマンドで読み込みます.

```zsh:Terminal
pip install -r requirement.txt
```

次のコマンドで正常にインストールされているか確認します.

```zsh:Terminal
pip list
```

以下のように表示されていれば成功です.

```zsh:Terminal
Package    Version
---------- -------
numpy      1.21.0
pandas     1.3.0
```

以上でvenvの導入は完了です.