OmniAICreator/Qiita-1.07M huggingface dataset:
Vue CLIアプリをApacheで動かすためのhtaccess設定

# はじめに

こんにちは、Gakken LEAP のバックエンドエンジニアの mizuno です。
Vue CLIで開発したシングルページアプリケーション（SPA）をApacheサーバーにデプロイして動作確認を行った際、ブラウザのリロードがうまくいかず、404エラーが発生するという問題に直面しました。
今回は、私が直面した問題の詳細と、どのように`.htaccess`で解決したかを、初心者の方にも分かりやすく解説していきます。

# `.htaccess`ファイルとは？

`.htaccess`ファイルは、Apacheの設定をディレクトリごとに変更するためのファイルです。
このファイルを使うことで、特定のディレクトリに対して、URLの書き換え、アクセス制限、カスタムエラーページの設定など、さまざまなカスタマイズを行うことができます。

# うまくいかなかった理由

問題の原因は、Vue Routerの設定をHistoryモードに設定しており、サーバーサイド（Apache）はURLに対応する実際のファイルやディレクトリが存在しない場合に404エラーを返すためです。
例えば、`/about`や`/contact`といったページにリクエストが送られると、サーバーはそのパスに該当するファイルを見つけられずエラーを返していました。

# 解決策と対応

Vue Routerの設定をURLに`#`が入るHashモードであれば、問題なく動作するのですが、Historyモードで動作させたい場合はリダイレクト設定を適用します。

この問題を解決するためには、Apacheがすべてのリクエストを`index.html`に渡すようにする必要があります。
できれば、`httpd.conf`に設定を記載したいところですが、レンタルサーバーでの実装だったため`.htaccess`で行いました。
これを実現するのが以下の`.htaccess`設定です。

```apache
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>
```

- `<IfModule mod_rewrite.c> ~ </IfModule>`
  - このブロック内の設定は、Apacheのmod_rewriteモジュールが有効になっている場合にのみ適用されます。このモジュールは、URLの書き換えを行うために必須です。
- `RewriteEngine On`
  - URL書き換え機能を有効にします。
- `RewriteBase /`
  - URL書き換えのベースとなるディレクトリを指定します。この例では、現在のディレクトリをベースとしています。
- `RewriteRule ^index.html$ - [L]`
  - index.htmlへの直接アクセスを許可します。[L]フラグは、以降のルールへの処理を中断します。
- `RewriteCond %{REQUEST_FILENAME} !-f`
  - 存在しないファイルへのリクエストでないことを確認します。
- `RewriteCond %{REQUEST_FILENAME} !-d`
  - 存在しないディレクトリへのリクエストでないことを確認します。
- `RewriteRule . /index.html [L]`
  - 上記の条件を満たす場合、すべてのリクエストを`index.html`にリダイレクトします。これにより、SPAのルーティングが機能し、ブラウザのリロード時にページ全体が再読み込みされることなく、Vueアプリが正常に動作します。

この`.htaccess`の設定により、以下のことが実現されます。

- SPAのルーティング
  - ブラウザが直接ファイルやディレクトリを要求した場合でも、`index.html`にリダイレクトすることで、Vue Routerなどのルーティングシステムが働き、SPAとして動作します。

# まとめ

Vue CLIで作成したSPAをApacheで動かすには、適切なリダイレクト設定が必要です。
この設定により、リロード時でも`index.html`にリダイレクトされ、Vue Routerのルーティングが正しく機能します。

:::note warn

- `.htaccess`の設定は、サーバー環境やプロジェクトの構成によって異なる場合があります。
- `.htaccess`の書き換えミスは、Webサイトにアクセスできなくなる可能性があるため、十分に注意してください。
:::

# エンジニア募集

Gakken LEAP では教育をアップデートしていきたいエンジニアを募集しています。
ぜひカジュアル面談でお話できればと思います。
https://gakken-leap.co.jp/recruit/

# 参考

- [HTML5 History モード](https://v3.router.vuejs.org/ja/guide/essentials/history-mode.html#%E3%82%B5%E3%83%BC%E3%83%8F%E3%82%99%E3%83%BC%E3%81%AE%E8%A8%AD%E5%AE%9A%E4%BE%8B)
Pyinstaller と multiprocessing 併用

# 並列処理のための標準モジュール multiprocessing を使ったコードを Pyinstaller で固める
注意：とんでもないことが起きます。
multiprocessing を使ったコードを
単にpyinstallerしてバイナリ化したモジュールを走らせると、、、
　1つ実行して停まるたびに、本来は存在しないはずの次の実行を延々と繰り返しよる！
　　下手すると同一処理が無数に走って世界を埋め尽します。
それだけでなく、このプロセスが繰り返し時に重複して走るために、重複していなければ起きない様々な例外を引き起こしてエラーメッセージでコンソールが埋め尽くされ何が原因か分からなくなるという副作用もあります。

## 重要：最初に freeze_support() を呼ぶ
WindowsでもPosixでもfreeze_support()は必要です。
2024年9月現在、「freeze_support() は Windows 限定」という説明は誤情報のようです。

:::note info
if _ _ _name_ _ __=='_ _  _ _main_ _ _':  の直後に置けという説示も見かけるが、本質的にはmultiprocessingを動かす前にmultiprocessing.freeze_support()を呼べ、ということでしょう。
multiprocessingの最初のインポートの直後に呼んでしまってよいと思う。
:::

↓　本家ドキュメントのP29あたりにあります。
https://pyinstaller.org/_/downloads/en/v6.4.0/pdf/
AWS移行戦略をわかりやすく解説

## はじめに

「AWSへの移行って、どこから手をつければいいの？」

AWSに興味はあるけど、いざ移行しようとすると、何から始めればいいのかわからない、という方も多いのではないでしょうか？

この記事では、AWS移行を成功させるための重要な要素である「移行戦略」について、超初心者の方でも理解しやすいように解説していきます。

### AWS移行は3つのフェーズで進む！

AWSへの移行は、大きく3つのフェーズに分けて進められます。

1. **準備フェーズ (アセスフェーズ)**：現状を分析し、移行目標や方法を検討
2. **移行フェーズ (モライフェーズ)**：移行計画を立て、AWS環境を構築
3. **最適化フェーズ (マグレアモダナイズフェーズ)**：移行後のシステムを検証し、最適化

特に移行の準備段階における**「移行戦略」**について詳しく解説していきます。

### 移行戦略とは？

移行戦略とは、**何を、なぜ、いつまでに、どのように移行するか**という方針のことです。

例えば、

* 自社のWebサイトをAWSに移行する場合、
    * どのサーバーを移行するか？ (Webサーバー、データベースサーバーなど)
    * いつまでに移行するか？ (契約期限、システム改修のタイミングなど)
    * どの方法で移行するか？ (既存のシステムをそのまま移行するのか、クラウドに最適化して再設計するのかなど)

といったことを明確にする必要があります。

### AWSが提唱する7つの移行パス

AWSでは、移行対象のシステムやサーバーごとに最適な移行方法を選択できるよう、7つの移行パスを提唱しています。

これらの移行パスは、それぞれ移行方法によって得られるメリットやコストが異なります。

**1. リロケート (Relocate)**：既存のアーキテクチャーをそのままAWSに移行します。移行が早く、クラウドの基本的なメリットを得られます。

**2. リホスト (Rehost)**：オンプレミスのサーバーをAWSのEC2へ移行します。リロケートと同様に、移行が早く、クラウドの基本的なメリットを得られます。

**3. リプラットフォーム (Replatform)**：アーキテクチャーを一部最適化して移行します。OSやミドルウェアのバージョンアップ、データベースサーバーをRDSに変更するなどが該当します。移行には時間がかかりますが、より多くのメリットを得られます。

**4. リファクター (Refactor)**：アーキテクチャーをクラウドに最適化して再設計します。モノリスなアプリケーションをマイクロサービス化したり、データベースのエンジンを変更したりすることが該当します。移行には多くの時間とコストがかかりますが、クラウドのメリットを最大限に引き出せます。

**5. リパッケー ジ (Repackage)**：  既存のシステムをパッケージ製品に置き換えます。

**6. リテイン (Retain)**：AWSに移行せず、既存環境で引き続き利用します。

**7. リタイア (Retire)**：システムを統合したり、廃止したりします。

### 移行戦略を検討するポイント

移行戦略を検討する際には、以下のポイントを考慮する必要があります。

1. **移行の目的を明確にする**

   * データセンターの契約期限が迫っていて、なるべく早く移行したいのか？
   * ピーク時の負荷が増加傾向にあり、安定性を確保したいのか？
   * ユーザーからの要望に素早く対応したいのか？

2. **システムの現状を把握する**

   * どのサーバーを移行するのか？
   * 各サーバーのスペックや利用状況は？
   * どのアプリケーションが稼働しているのか？
   * 必要なセキュリティレベルは？

3. **時間とコストの制約**

   * いつまでに移行を完了させたいのか？
   * どの程度の予算を移行にかけられるのか？

### まとめ

AWSへの移行は、適切な移行戦略を立てることが成功の鍵となります。

7つの移行パスを理解し、それぞれのメリットとデメリットを考慮して、組織のニーズに最適な移行方法を選択しましょう。

### 関連記事
[移行戦略 (7R) の概要【AWS Black Belt】 - YouTube](https://www.youtube.com/watch?v=yp0F09vaC6o)
[移行戦略 (7R) の概要【AWS Black Belt】 - PDF](https://www.youtube.com/redirect?event=video_description&redir_token=QUFFLUhqa0dycW5PU0x3Q3RBTktlRWc0UWZJUmlzcDNvUXxBQ3Jtc0ttckhPQTVwMU5aNHRFOUlMbkJyaU1WdDFjTkU1bE1FcGZ0MXlNQmZPMTAtUXdjMXQzVkhQTTAzY0l2NlAxWWY5YUY0azhoUzB5SmY0eVhnd1RmeTdBaklBWFhpUTRUcGcwWl81OUtSQ1NxV0ZBMnl3QQ&q=https%3A%2F%2Fpages.awscloud.com%2Frs%2F112-TZM-766%2Fimages%2FAWS-Black-Belt_2023_Migration-7R_1208_v1.pdf&v=yp0F09vaC6o)
統計検定2級　難易度の高い過去問解説 2016年問10

Zennで私が記事にしていた内容を転写しています。

---

統計検定2級の資格獲得を目指している方に対する記事です。

2016年6月の問10の設問の日本語がすこし雑なためか、私には理解ができませんでした。
そのため、問10の（２）と（３）に関して、私なりに理解できた内容に基づき、解説します。

## 問１０（２）
得票率の推定値として0.45を用います。この推定値に対する推定量の統計的性質について選択肢から選びます。ここではまず「一致推定量」と「不偏推定量」の理解が必要です。

**一致推定量（Consistent Estimator）**
一致推定量は、サンプルサイズが大きくなるにつれて、その推定値が真のパラメータに収束する性質を持つ推定量です。ここで、得票率の推定値はサンプルサイズが増えるにつれて真の得票率に収束することが期待されます。

**不偏推定量（Unbiased Estimator）**
不偏推定量は、サンプルから得られる推定値の期待値が真のパラメータと等しい場合の性質を持つ推定量です。選挙の出口調査で得られた得票率の推定値は、サンプルが母集団を代表する限り、真の得票率を正確に推定すると考えられます。

このことから、
出口調査の結果から得られた得票率の推定値 0.45 は、
一致推定量である：サンプルサイズが大きくなるにつれて、推定値は真の得票率に収束すると期待されます。大数の法則です。
不偏推定量である：推定値の期待値は、真の得票率に等しいと考えられます。つまり期待値＝平均なわけですから、得票率の標本平均は、真の得票率に等しいといえます。

&nbsp;
&nbsp;

## 問１０（３）
もともと得票率の母比率の推定問題なわけですから、分散といえば$np(1-p)$です。$n$ は試行回数、$p$ は各試行で「成功」する確率です。では、なぜ選挙の出口調査のような標本比率の分散の推定には $p(1−p)/n$という式が使われるのでしょうか。これを理解するには、二項分布の性質と標本比率の概念を理解する必要があります。

**二項分布の分散**
二項分布は、同一の確率 $p$ で「成功」または「失敗」となる独立な試行を $n$ 回行ったときの「成功」回数の分布です。
二項分布の分散=$np(1-p)$

**標本比率の分散**
一方、標本比率は、二項分布の成功回数を試行回数で割ったものです。例えば、2000回の試行で900回成功した場合、標本比率は 900/2000=0.45です。標本比率の分散は、二項分布の分散を試行回数の平方で割ったものになります。したがって、標本比率の分散は次のように表されます：

標本比率の分散 = $np(1-p)/n^2=p(1-p)/n$
 

理由
この違いの理由は、二項分布の分散が「成功」回数の分散を表しているのに対し、標本比率の分散は「成功」の割合の分散を表しているためです。サンプルサイズ（試行回数）が大きくなるにつれて、標本比率の分散は小さくなります。これは、大きなサンプルサイズでの比率の推定がより正確であることを意味します。


もっと簡単・かつ端的・かつ資格対策に限定して表現すると、母比率の区間推定において母分散が未知の場合推定量tが採用されます。その際の分母にはいる、**$√(p(1-p)/n)$が標本比率の標準偏差であり、${√(p(1-p)/n)}^2$が標本比率の分散**というわけになります。
スワップ領域を作成する

# 環境
ec2(micro),Ubuntu24.04

# スワップ領域を確認する
```
*******@********:~/*******$ free -h
               total        used        free      shared  buff/cache   available
Mem:           957Mi       719Mi       235Mi       892Ki       150Mi       237Mi
Swap:             0B          0B          0B
```
スワップ領域はなかった。

# スワップ領域を作成する

https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/7/html/storage_administration_guide/ch-swapspace#swap-extending-lvm2

https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04-ja

# 感想
これらの流れで作成することができた。
よかった。
投稿 45 動的なページ 2024/08/14

本日の勉強時間　0.5H

動的なページとは、クライアントから送られてきたデータ、
もしくは、その他の条件にもとづいて、異なる値が出力されたデータのこと。
処理するのがクライアント側か、サーバーサイド側かによって
分類できる。
PHPは代表的なサーバーサイド技術。
Rustacean（ラステイシャン）になりたい。1-1：もうちょっと可変変数について

# はじめに
いぜん、[Rustacean（ラステイシャン）になりたい。1: 可変変数、不変変数](https://qiita.com/SP-ya/items/88fd87e09b7fedfac5d0)　
で、可変変数について書きました。
その時は、「変数を上書きできる、できない」観点で書きましたが、可変変数についてもう少し書きます。

# 動的配列（ベクター）の値を操作する場合は、可変変数であること
この例はコンパイルエラーになります。
```rust
let v = vec![];

// 1を追加
v.push(1);
```
![{92A43467-6907-4DF8-AFFF-D099B1E22D75}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/625a52b5-82ea-d9a9-d1b9-05141e231b63.png)

pushメドッソのシグネチャを確認すると
```rust
// 要素をコレクションの後方に加えます。
pub fn push(&mut self, value: T)
```
`&mut self`となっているので、pushを使いたい場合は`mut`宣言する必要があります。
上記のエラーも`mut`使えってアシストしてますね。

:warning: `&mut self`については、「メソッド宣言」編の時に説明します。

`mut`宣言すればエラーになりません。
```rust
let mut v = vec![];
v.push(1);　// [1]
```

# 文字列の値を操作する場合は、可変変数であること
文字列(String)も同じです。
`mut`宣言無しで、```push_str```などの値を操作するメソッドを使用するとコンパイルエラーになります。
```rust
let s = String::new();
s.push_str("SP");
println!("{}", s);
```
![uploading...0]()

push_strメドッソのシグネチャを確認すると
```rust
// 文字列スライスを後方に加えます。
pub fn push_str(&mut self, string: &str)
```
こちらも`&mut self`となっているので、push_strを使いたい場合は`mut`宣言する必要があります。

<mark>値を操作するメソッドを呼び出す場合は、「可変変数」として宣言しましょう。</mark>

以上でした。
AWS EC2とS3のコスト比較分析（ap-northeast-1リージョン）

2024年9月現在の話

# AWS EC2とS3のコスト比較分析（ap-northeast-1リージョン）

## 結論

S3を使用することで、純粋なストレージコストを50-75%以上削減できる可能性があります。さらに、アクセス頻度の低いデータをGlacierクラスに移動することで、最大98%のコスト削減が可能です。

ただし、頻繁なデータアクセスや大量のデータ転送がある場合は、追加コストが発生する可能性があるため、実際の使用パターンに基づいて総合的に判断する必要があります。

## EC2のストレージコスト

1. EBS（Elastic Block Store）の料金:
   - 汎用SSD（gp3）: $0.0912 per GB-month
   - 例: 100GB使用の場合、月額 $9.12

2. EC2インスタンス自体のコスト（参考）:
   - t3.micro（2 vCPU, 1 GiB RAM）: $0.0132 per hour
   - 1ヶ月（730時間）使用の場合、約 $9.64

## S3のストレージコスト

1. S3 Standard:
   - 最初の50 TB/月: $0.025 per GB-month
   - 例: 100GB使用の場合、月額 $2.50

2. S3 Intelligent-Tiering:
   - ストレージ料金: $0.025 per GB-month
   - 監視及び自動化料金: $0.0025 per 1,000 objects
   - 例: 100GB、10,000オブジェクトの場合、月額 $2.525

3. S3 Glacier Deep Archive（長期保存向け）:
   - $0.002 per GB-month
   - 例: 100GB使用の場合、月額 $0.20

## コスト比較（100GB使用の場合）

1. EC2 + EBS: $9.12/月（インスタンスコスト除く）
2. S3 Standard: $2.50/月
3. S3 Intelligent-Tiering: $2.525/月
4. S3 Glacier Deep Archive: $0.20/月

## 追加考慮事項

1. データ転送コスト:
   - S3からのデータ転送: 最初の1 GB/月は無料、その後$0.114 per GB
   - EC2からのデータ転送: 同じリージョン内なら無料、リージョン外へは課金

2. リクエストコスト（S3）:
   - PUT, COPY, POST, LIST リクエスト: $0.0053 per 1,000 requests
   - GET, SELECT, その他のリクエスト: $0.00042 per 1,000 requests

3. S3のライフサイクルポリシー:
   - 古いデータを自動的に安価なストレージクラスに移動可能
TypeScript 型の絞り込み（Narrowing）その1

:beginner: TypeScript初心者向けです。
TypeScript 型の絞り込み（Narrowing）の話です。
# 型判定メソッドを作った場合は、type predicate機能を使おう。

文字列型(string)であるか判定するメソッド「isStrring」を作成してみました。
引数の値がstringならtrue、でないならfalseを返すメソッドです。

```typescript
function getValue(): string | number | undefined {
  return 'SP';
}

function isString(value: string | number | undefined): boolean {
  return typeof value === 'string';
}

const value: string | number | undefined = getValue();

if (isString(value)) {
  // エラーになる。
  // Property 'length' does not exist on type 'string | number'.
  // Property 'length' does not exist on type 'number'.ts(2339)
  const len = value.length;
  console.log(len);
}
```

この例では、せっかくisStringで文字列型判定しているのに、
TypeScriptがvalueをstring型と認識出来ず
```value.length```
がエラーになります。

<mark>**これを解決するには、**</mark>
<mark>**型判定メソッドはtype predicate機能を使います。**</mark>

## type predicate機能
isStringメソッドをtype predicate機能を使って実装しました。
```typescript
// type predicate機能を使って実装
function isString(value: string | number | undefined): value is string {
  return typeof value === 'string';
}

const value: string | number | undefined = getValue();

if (isString(value)) {
  // valueがstring型と認識される
  const len = value.length;
  console.log(len);
}
```

 type predicate機能は、戻り値が
 ```引数変数名 is 判定型```
となります。

今回の例では、引数変数名が「value」、判定型が「string」なので
```value is string```
になります。

型判定メソッドは、TypeScriptが型の認識が出来るように、type predicate機能を使いましょう。

### TypeScript5.5では、type predicate機能の型推論が賢くなった
TypeScript5.5では、type predicate機能の型推論が賢くなって、
戻り値に
 ```引数変数名 is 判定型```
 を実装しなくてもOKになりました。
 ```typescript
// 型推論版
function isString(value: string | number | undefined) {
  return typeof value === 'string';
}
```

# 参考資料
[型ガード関数 (type guard function)](https://typescriptbook.jp/reference/functions/type-guard-functions#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%AE%9A%E7%BE%A9%E3%81%AE%E5%9E%8B%E3%82%AC%E3%83%BC%E3%83%89%E9%96%A2%E6%95%B0)

[Using type predicates](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates)
Next.js+supabaseで商品成分サーチアプリを作ってみた話３（検索機能）

※初心者のため、間違いや何かご存じの方がいましたら、教えていただけると助かります。

# 作ったもの
https://keshohin-seibun.vercel.app/

# 今回の内容
アプリ内で剣先機能を2か所（商品名検索、成分検索）実装して、手順が理解できたため整理します。


### 環境
windows11
docker-desktop
Next.js(app routerを使用)
supabase
ホスティング：Vercel

## 手順
１. page.tsxにuseState()で、検索語を保持する。初期値は空文字（""）
```tsx
const コンポーネント名 = () => {
    ...
    const [searchTerm, setSearchTerm] = useState("");
    ...
```

２. returnの中に、検索する語句を入力するための入力タグ(inputタグ)を作成する。
　onChange={(e) => setSearchTerm(e.target.value)とすると、検索語を入力するたびに検索・抽出が実行される。もし、🔍ボタンを押したときのみ実行したいなら、buttonタグを別に作って、onClickから、(e) => setSearchTerm(e.target.value)を呼び出すようにする。
```tsx
 <input
                className={styles.input}
                type="text"
                placeholder="検索ワードを入力"
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
            />
```
 
３. 検索対象のlistsを、検索語でフィルタリングした、filteredList（変数。名前はなんでもよい）を作成する。
```tsx
const filteredLists = lists.filter((item) =>
        item.A.includes(searchTerm) //Aには、検索語で対象にするプロパティ名（データベースの列名）を入れる。
    );
```

４. return内のlists.map~の記述で、lists → filteredListsに変更する。
```tsx
    {filteredLists.map((product) => (
        <Link>
            {product.A}
        </Link>
    ))}
```

これで、検索語が変更されるたびに、リストフィルタリングされたものが画面上に表示される。
なおアプリ内で、商品に成分を登録するページにも実装したが、チェックボックスのチェック有無は変更されなかった。（チェックしたものが、検索後に外れることは無かった。）
あくまで、「プラウザの見た目上で」フィルタリングされる（見えなくなる）だけだと思われる。


## まとめ
今回のアプリでは、リストを全部取得したうえで検索する機能としたため、想像以上に簡単かつ、高速だった。
ただし、リストをクライアントに全部渡さずに表示させる場合は、データベース（今回はsupabase）からデータを取得する段階で条件指定しなければならないと思われる。
なお、今回設定しなかったが、検索に一致するものが無かった場合は、{!filteredLists ? "一致なし" : filteredLists.map(()=>... }などとして、ユーザーに「一致が無かったこと」を伝えたほうが良さそう。

次回は、return内のテーブルセルの値によって、セルの色を変えるように、CSSで条件分岐した方法についてまとめておきたい。

<br/>

https://qiita.com/yassyjk/items/39406ae25376b7d64c71

https://qiita.com/yassyjk/items/0f7ad40e9116977c961b
投稿 44 サーバーの種類 2024/08/13

本日の勉強時間　0.5H

▪️WEBサーバー
HTMLをかえすサーバー
（PHPでつくったWEBサイトを公開する場合、WEBサーバーにPHPを入れる必要がある）

▪️データベースサーバー
データをかえす
(Android / Kotlin) ホーム画面に設定する方法 (メモ)

**最終変更日:** `2024/09/11`
**最終検証日:** `2024/09/11`

### 設定方法

1. パーミッションの設定 (app/src/main/**AndroidManifest.xml**)
2. 確認画面の表示 (app/src/main/java/**{スラッシュ区切りのID}**/**MainActivity.kt**)

## パーミッションの設定

`app/src/main/AndroidManifest.xml`に次の内容を追加
(`activity/intent-filter`内に追加)

```xml
<action android:name="android.intent.action.MAIN" /> <!-- この行は既にあるかも -->
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
```

## 確認画面の表示

`MainActivity.kt`内の`onCreate`関数の適切な場所(例: `最後`)に次の内容を追加

```kotlin
// Android 10以降かどうか確認
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    val roleManager = getSystemService(RoleManager::class.java)
    if (roleManager != null && !roleManager.isRoleHeld(RoleManager.ROLE_HOME)) {
    // ホームアプリとしてのロールをリクエスト
        val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME)
        startActivityForResult(intent, REQUEST_CODE_ROLE_HOME)
    }
}
```
投稿 42 ローカル開発環境 2024/08/11

本日の勉強時間　0.5H

PHPはデータを記憶することは苦手。
なので、データベース（コンピュータ上で集積・整理された情報群のこと）を使う。

ブラウザでPHPを確認するには、PHPはWEBサーバの中にいてもらわないといけない。

そこで、、、-ローカル開発環境は

サーバにアップせずPHPが書き換えたHTMLを確認できる。
【VSCode】Spring Bootアプリケーション起動時にThe container 'Project and External Dependencies' references non existing library

# はじめに
VSCodeにて、gradleの依存エラーに遭遇したので備忘録を残します。

(VSCodeでgradle開発やってるとちょくちょくこういう依存エラーでてきて困る…)

# 問題
VSCodeにてSpring Bootアプリを起動すると、以下のようなエラーが出る。

```
The container 'Project and External Dependencies' references non existing library 'C:\Users\＜ユーザー名＞\.gradle\caches\modules-2\files-2.1\org.testcontainers\junit-jupiter\1.20.0\51b4de4f3d788fafbe7fd3a4a3ff1ac44206822d\junit-jupiter-1.20.0.jar'
```

自分のbuild.gradleのdependenciesには以下を記載
↓
```
testImplementation "org.testcontainers:junit-jupiter:latest.release"
```

エラーは、junit-jupiterの1.20.0.jarなんてライブラリは存在してないから参照できないよ、みたいなことを言われている。

たしかに、ビルドでできる`C:\Users\＜ユーザー名＞\.gradle\caches\modules-2\files-2.1\org.testcontainers\junit-jupiter\`配下には1.20.0は存在してなくて、現在最新版である1.20.1が作成されている。

なんでアプリ起動時に新しいバージョンである1.20.1を見にいってくれないんだろう。。
→VSCodeのなにかのキャッシュが悪さしていそう


# 解決方法

VSCodeの設定ファイルがある、
`C:\Users\＜ユーザー名＞\AppData\Roaming\Code\User\workspaceStorage`配下を全削除

# おわりに
ちょっとめんどくさいけど、VSCodeでgradle開発中に依存がおかしくなったら脳死でAppData\Roaming\Code\User\workspaceStorage配下を全削除していいかも。

(他にもっといいやり方がないかは模索中…)
NimbleCSVを使ってCSVの読み書きをする

# プロジェクト作成
```
$ mix new csv_experiment
$ cd csv_experiment
```

# NimbleCSVの設定

```diff_elixir:csv_experiment/mix.exs

defmodule CsvExperiment.MixProject do
  # 〜省略〜

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
+     {:nimble_csv, "~> 1.2"}
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end
end
```

```
$ mix deps.get
```

# ソースを書く
```elixir:lib/csv_experiment.ex
NimbleCSV.define(Csv, [])

defmodule CsvExperiment do
  @moduledoc """
  Documentation for `CsvExperiment`.
  """

  @doc """
  Hello world.

  ## Examples

      iex> CsvExperiment.hello()
      :world

  """

  @range 1..9
  @csv_file_name "multiplication.csv"
  def hello do
    list = creat_multiplication_list()
    IO.puts("------------ 掛け算リスト ------------")
    IO.inspect(list)

    IO.puts("------------ 掛け算CSV作成 ------------")

    list
    |> wite_csv!(@csv_file_name)

    File.read!(@csv_file_name)
    |> IO.inspect()

    IO.puts("------------ 掛け算CSVロード ------------")

    read_csv!(@csv_file_name)
    |> IO.inspect()

    :world
  end

  def wite_csv!(data, path) do
    data
    |> Csv.dump_to_iodata()
    |> IO.iodata_to_binary()
    |> then(&File.write!(path, &1))
  end

  def read_csv!(path), do: File.read!(path) |> Csv.parse_string(skip_headers: false)

  def creat_multiplication_list() do
    for x <- @range do
      for y <- @range, do: x * y
    end
  end
end
```

# 実行

```
$ mix run -e "CsvExperiment.hello"
```



```:実行結果
------------ 掛け算リスト ------------
[
  [1, 2, 3, 4, 5, 6, 7, 8, 9],
  [2, 4, 6, 8, 10, 12, 14, 16, 18],
  [3, 6, 9, 12, 15, 18, 21, 24, 27],
  [4, 8, 12, 16, 20, 24, 28, 32, 36],
  [5, 10, 15, 20, 25, 30, 35, 40, 45],
  [6, 12, 18, 24, 30, 36, 42, 48, 54],
  [7, 14, 21, 28, 35, 42, 49, 56, 63],
  [8, 16, 24, 32, 40, 48, 56, 64, 72],
  [9, 18, 27, 36, 45, 54, 63, 72, 81]
]
------------ 掛け算CSV作成 ------------
"1,2,3,4,5,6,7,8,9\n2,4,6,8,10,12,14,16,18\n3,6,9,12,15,18,21,24,27\n4,8,12,16,20,24,28,32,36\n5,10,15,20,25,30,35,40,45\n6,12,18,24,30,36,42,48,54\n7,14,21,28,35,42,49,56,63\n8,16,24,32,40,48,56,64,72\n9,18,27,36,45,54,63,72,81\n"
------------ 掛け算CSVロード ------------
[
  ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
  ["2", "4", "6", "8", "10", "12", "14", "16", "18"],
  ["3", "6", "9", "12", "15", "18", "21", "24", "27"],
  ["4", "8", "12", "16", "20", "24", "28", "32", "36"],
  ["5", "10", "15", "20", "25", "30", "35", "40", "45"],
  ["6", "12", "18", "24", "30", "36", "42", "48", "54"],
  ["7", "14", "21", "28", "35", "42", "49", "56", "63"],
  ["8", "16", "24", "32", "40", "48", "56", "64", "72"],
  ["9", "18", "27", "36", "45", "54", "63", "72", "81"]
]
```


# ソース(github)
https://github.com/ymn-t-yamanashi/csv_experiment
投稿 40 エンジニアの面接におけるポートフォリオの役割 2024/08/09

本日の勉強時間　0.5H

ポートフォリオの立ち位置は「メニュー表」。

・エンジニアに対する興味
・努力量

の客観的なアウトプットで、ポテンシャル、自走力が求められる。

未経験エンジニアが作るポートフォリオは必ずしもクオリティが高いものではないが、技術素養、基礎力が垣間見えるといい。
投稿 39 未経験エンジニアのエントリー 2024/08/08

本日の勉強時間　0.5H
エンジニアになるためには、最大限クオリティの高い

・履歴書
・職務経歴書
・ポートフォリオ
を作って、自分の総合力をアピールする。　

面接は総合旅行。総合力とは、会社にとっての利益、採用されたときのメリットを言えるようにする。
WebDeveropperVootcamp HTML/CSS/JavaScript編その２

# デフォルト引数
関数名(引数=デフォルト値)で引数を与えなかった場合の挙動を指定

# スプレッド構文
- 配列の中身を渡す
- math.max(配列名)では配列のアドレスが渡されるだけ
- math.max(...配列名)なら〇

## スプレッド構文を用いたオブジェクトの操作
- オブジェクト１={〇〇｝,オブジェクト2={××｝があるとする。
- オブジェクト3 ={...オブジェクト１}でオブジェクトのコピー
- オブジェクト4 ={...オブジェクト１,...オブジェクト2}においてかぶっているプロパティ名がある場合:オブジェクト2のプロパティが優先される。

# レスト構文
- スプレッド構文と似ているが違うもの
- 関数名(...引数名)とすることで引数に配列を渡せる
- print(...num){console.log(num)}; print(1,2,3); /*[1,2,3]*/


# タグ操作
- タグ.append(内容)でテキスト内容や他のタグを操作対象のタグの中に入れ込むことができる

# DOM操作
## テキスト操作
- 通常のテキスト操作:要素.innerText = "A"
- HTML要素を含めたテキスト操作:要素.innerHTML = <ディヴ>A<ディヴ>'

## 親子要素操作
- 親:要素.parentElement
- 子供:要素.childElement
- 兄弟:要素.nextElementSibling

## 要素の追加
step1 A = document.createElement()でタグを作る
step2 中身を設定する A.innerTextなど
step3 親.appendChild(A)で場所を決める
　　  もしくはinsertAdjacentElement("兄要素",A)

## 要素の削除
A.remove()

## 属性操作
- 属性名 class,属性値 A　(class="A")という属性に対して
- getAttribute("属性名")などでそのクラスの属性を取得
- setAttribute("属性名",属性値)
### class操作
- クラス属性値の追加:要素.classList.add()
- クラス属性値のつけ外し:要素.classList.toggle()
### name操作
- elements.name属性値でアクセスできる
## スタイル操作
- 要素.style.color="red"


# DOMイベント

## クリックイベント
addEventListener("click",関数)

## フォームイベント
HTML内のform-inputタグで起こるイベントはどこか(action="")に情報を送信する際にページの切り替えが起こる。
- submit:帰ってきた情報を基に処理を行う。ページのリフレッシュは起こる。
- e.prepentdefault():デフォルトの動作(ページのリフレッシュ)を止めることができる。ちゃんと情報の送信などはできる
- フォームに記入された内容:要素.valueで獲得できる。




## thisの値
呼び出し*元*のオブジェクトに依存する
データとして記録された最新7日間を抽出する(SPSS Modeler データ加工逆引き1-21)

# データとして記録された最新7日間を抽出する

![スクリーンショット 2024-09-02 12.51.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/c35884f5-5abb-dd35-8f2b-6708f9246f50.png)

## 1.想定される利用目的

・定形レポートのための抽出
・SPSS　CADSを利用したストリームの自動化

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/raw/main/latest7days_data.str

## 3.サンプルストリームの説明

![スクリーンショット 2024-09-02 13.44.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/73389300-cf85-1a02-db03-e53346c11e10.png)

a.入力するデータは以下の通りです。日付と部問名（Cate）にランダムな実績値(Value)を割り当てています。
このデータの最新の記録は2024年9月11日です。

![スクリーンショット 2024-09-02 15.50.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/319d1a5f-e245-c8a0-8174-936a866d9ed4.png)

#### レコード結合で日付の最大値のみを抽出する

b.[レコード集計]ノードを編集します。

![スクリーンショット 2024-09-02 13.30.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/14a0d930-f590-b684-d824-9eeecd0b6fa5.png)

[プレビュー]します。　

![スクリーンショット 2024-09-02 13.30.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/30180a4c-e0cc-b20e-df4c-60c8fd858889.png)

c.[フィルター]ノードを編集します。

![スクリーンショット 2024-09-02 13.30.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/678f4054-8beb-028f-a49f-5ccc931c8f6e.png)

d.[レコード結合]ノードを編集します。

![スクリーンショット 2024-09-02 13.31.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8e6c85cf-631e-d526-49ed-183dd86211e7.png)

[テーブル]を実行します。　　Valueはランダムなので毎回変わります。

![スクリーンショット 2024-09-02 13.31.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/e8a8bcba-6769-646c-8a7f-84e8557dccb8.png)

#### 最新日までの移動7日間を抽出する

e.[レコード結合]ノードを編集します。キーをブランクにして、１対N結合をします。

![スクリーンショット 2024-09-02 13.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/52165205-79a0-dfed-3f99-4c14367cd9c6.png)

[プレビュー]します。　

![スクリーンショット 2024-09-02 13.32.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/255b2b0c-2569-0881-1aba-d4986dc81f5d.png)

f.[条件抽出]ノードを編集します。Modeler18.5以降に搭載された関数[date_add_days]を利用します。本来N日後に使う関数ですがマイナスを利用しN日前を表現できます。

![スクリーンショット 2024-09-02 13.32.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/82aac163-f419-06b3-3e63-8be9ea3a897c.png)

[date_add_days]は以下の記事で詳しく取り上げています。

https://qiita.com/416nishimaki/items/b5c30d27573625c4f89f

[テーブル]を実行します。　Valueはランダムなので毎回変わります。

![スクリーンショット 2024-09-02 13.32.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8a2dd02c-f39c-651b-2535-3873ace2d554.png)

#### 注意事項

Ver１８.４以前をお使いの方は関数[date_add_days]がありませんので　gのように基準時間を利用した記述にします。

![スクリーンショット 2024-09-02 13.33.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/277a1d59-2a46-acb9-911a-e9d7ba41963f.png)


## 4.参考情報

#### タイムスタンプの差の計算

https://qiita.com/kawada2017/items/8e1291801aacf5427e7d

#### よく使う「日付と時間」関数

https://qiita.com/Makimaki2020/items/72e3b774039327fa4ac4

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
ゼロから作る Deep Learning; 輪読

# ゼロから作る Deep Learning; 輪読
これは「ゼロから作る Deep Learning」のちょっとした知識メモです。Deep Learningの索引のように使用できればと思います。

## ニューロン（ノード）と呼ばれる入力値とその総和で作る式の意味

バイアスの項含めた入力信号の総和(= $\sum_i^n w_i x_i + b$)が０より大きい時、y =１を出力し、０以下の時y = 0を出力する。

i = 2の時、次になる。
```math
\begin{equation} y=
    \left\{
    \begin{aligned}
         1 \space (w_1 x_1 + w_2 x_2 + b > 0) \\
        0 \space (w_1 x_1 + w_2 x_2 + b <= 0) \\
    \end{aligned}
    \right.
\end{equation}
```

$\sum_i^n w_i x_i + b$ について、${w_i}$ ${b}$  はパラメータであり、${x_i}$ は入力値である。

入力値の一つ一つはニューロンと呼ばれる。これは、入出力の変換様式が、神経細胞の流れのようであることに由来する。


```math
h(x) := w_1 x_1 + w_2 x_2 + b
```
このようにおく。

h(x)は、出力値が０より大きいか、０以下かによって、$\{1, 0\}$ に出力を制御する関数を使用する。

このような関数を活性化関数と呼ぶ。

## 活性化関数

ステップ関数、シグモイド関数、ReLU関数は活性化関数である。
ニューラルネットワークでは、シグモイド関数とReLU関数を使用する。


### シグモイド関数
シグモイド関数は、次のように出力に $0 < x < 1 $ の実数値を取る。これが、ステップ関数との違いである。


```
>>> import numpy as np
>>> def sigmoid(x):
...     return 1 / (1 + np.exp(-x))   
... 

>>> x = np.array([-1.0, 1.0, 2.0])
>>> sigmoid(x)
array([0.26894142, 0.73105858, 0.88079708])
```
plotすると次のようになる。

```
x = np.array([-1.0, 1.0, 2.0])
y = sigmoid(x)
import matplotlib.pyplot as plt
import numpy as np
# import matplotlib.pylab as plt
 
plt.xlabel('X')
plt.ylabel('Y')
plt.plot(x, y)
```

図のように出力値は $0<= y <= 1$ の実数値をとる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443312/ceb5846d-3696-794a-3f4f-dc23425ff116.png" width="400">

シグモイド関数では、このように実数値を取るので、層を重ねた時に都合が良い。

### 活性化関数の性質

- $y \in \[0, 1\]$ となる値をとる
- 入力値が大きいほど、出力は１に近づき、小さいほど０に近づく
- 非線形

非線形であることは層を作る上で大事な性質となる。
【SQL】GROUP BYの使い方を理解しておく

こんにちは、sqlを絶賛勉強しているものです。

本日はGROUP BYについて基礎理解が抜けており理解に時間がかかったのでそれを記事にしたいと思います。

# GROUP BYとは
GROUP BYとは、あるデータベースについてグループを作り集計関数（SUM,AVG,COUNTなど）をすることができます。

GROUP BY を使用する際、SELECT 句に指定できるのは以下の2種類だけです。
1. GROUP BY 句で指定したカラム（下記コードではpurchase_at）
2. 集計関数（SUM, AVG, COUNT など）を使用したカラム

つまり、<strong>GROUP BYは単にグループ化をするだけでなく計算（SUM, AVG, COUNT など）もセットで行うことを想定している</strong>ということです


## Progageでの例

GROUP BYを用いるうえでの注意点を以下のコードを用いて説明しておりました。

```sql:groupby.sql
〇正しいコード
SELECT SUM(price),purchase_at
FROM purchases
GROUP BY purchase_at;

×誤りのコード
SELECT price,purchase_at
FROM purchases
GROUP BY purchase_at;
```

私は上記の誤りのコードを見て、「あれ？purchase_atをGROUP BYでグループ化したのだから、priceでも問題なく出力できるのでは？と考えてました。」

SUMを使用せずにSELECT priceを使用したら以下のように出力されるから何が誤りなのかわかりませんでした。


| price | purchaed_at |
|:-:|:-:|
| 300 | 2024-09-09 |
| 80  | 2024-09-09  |
|   |   |
| 400  | 2024-08-30  |
| 250  | 2024-08-30  |
|   |   |
| 150  | 2024-07-15  |
|120   |2024-07-15   |

## 私が理解できなかったこと

私は以下のことを理解していなかったのでGROUP BYの理解に時間がかかりました。

* SELECTの後ろには集計関数（SUM, AVG, COUNT など）、GROUP BY 句で指定したカラム（下記コードではpurchase_at）しかおけない。
* GROUP BYはグループ化するだけでなく計算もセットに行う。

<br>
特に2つ目の計算もセットに行うということがsqlで初めて学んだことで、今まで扱ってきたデータは計算をしなくてもグループ化することがあったのでとても驚きでした。

上記を踏まえて以下のコードの問題点を見てみましょう。

```sql:groupby.sql
SELECT price,purchase_at
FROM purchases
GROUP BY purchase_at;
```

明らかだと思いますが、集計関数（SUM, AVG, COUNT など）を使用したカラムが含まれていません。

計算を想定しているGROUP BYにふさわしくないコードであるためエラーが出るということです。

# まとめ

今回は私が陥ったGROUP BYの落とし穴について解説しました
SELECTの後ろには集計関数（SUM, AVG, COUNT など）、GROUP BY 句で指定したカラム（下記コードではpurchase_at）しかおけない。

ということについては、文字通り書いていたので私のミスリードですが、計算をセットに行うことを想定していたGROUP BYの特性を知ることができていい勉強になりました。
CELTF ToDo管理サービス writeup

## 認証トークン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/f44bed54-fdbe-05f0-1ac9-54941dfd9dd0.png)
ログイン画面が渡される。
適当なPasswordを入力した後、Networkタブを見てみると、URLが書いてある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/4c50803a-6917-9cda-ea9e-13c630c8c8cc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/8cb194f4-4821-1602-4f97-13b2aaf4b8de.png)
アクセスすると、パスワードがあった。

## 預託認証トークン
認証トークンを預かった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/a0ae4b2e-641d-7c12-c8ed-fc6583db8353.png)
john the ripperで総当たりを試してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/6da14582-7fd4-8efd-412a-fbe81971d42c.png)
rockyou.txtにはないっぽいから単純な総当たり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/10289c12-76d2-c2e2-e651-1975e85724a8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/651eb53c-5e2a-7517-cdc2-fe91bd0c6a8c.png)
password:3b8afc

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/a4e8d873-0138-8f2e-46a6-f4c6b2c3358b.png)
トークンが手に入る。

## 復号キー
認証トークン:e852b4f2-37c0-4403-8df1-faea8805d41b
暗号化トークン:VllRAlMDBAEAAlJbVQAABwULAABTX1IAVFldWQsBVg1TBAUA
XORすればトークンが手に入りそう。(コードはAI)
```python
import base64

# Given inputs
e_base64 = "VllRAlMDBAEAAlJbVQAABwULAABTX1IAVFldWQsBVg1TBAUA"
p_hex = "e852b4f2-37c0-4403-8df1-faea8805d41b"

# Convert e from base64 to bytes
e_bytes = base64.b64decode(e_base64)

# Convert p from hexadecimal to bytes, ignoring the dashes
p_bytes = bytes.fromhex(p_hex.replace("-", ""))

# XOR the two byte arrays
xor_result = bytes([e_byte ^ p_byte for e_byte, p_byte in zip(e_bytes, p_bytes)])

# Convert the result to a readable format (e.g., hexadecimal)
xor_result_hex = xor_result.hex()

xor_result_hex
```

## 他ユーザー認証トークン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/9695c1a9-bab4-f8d3-a0b1-2579db77e316.png)
userid=1が気になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/47ff8df7-6045-acf9-94fd-5ca402d19a33.png)
2にしてリロードしたらフラグが取れた。

## 特権ログイン
gobusterで列挙したらadminが出てきた。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/087eefe0-a801-5cf3-cd5e-a18d172a9a24.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/772aac2e-e0e6-d0ff-5120-115fe964b884.png)

htmlを見てたら、答えがあった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3563446/0a65b520-7e8e-8116-0cfa-ce824658d636.png)
「存在」の概念とJSのif文

if文の()の中に `null`, `undefined`, `0`, 空文字(`''`)を入れると `false` の場合と同じように処理されるのが、西洋的で面白いと思った。

> さらに、「真」という意味で「存在」「ある」が、「偽」という意味で「非存在」「あらぬ」が用いられるばあいもある。

（引用：松浪 信三郎. 実存主義 (岩波新書) . 株式会社 岩波書店. Kindle 版）

JavaScriptにおいてif文が判定しているのは「存在と無（非存在）」であると言うことができるのかもしれない。

追記：ちょっと違った（cf. 頂いたコメント）
ローカルの変更を破棄して特定のコミットにリセットする手順

## 説明
Gitで作業を進める中で、ローカルでの変更を破棄して過去の特定のコミットに戻したい場合があります。その際、git reset --hard コマンドを使用することで、ローカルの変更を完全に破棄し、特定のコミットにリセットすることが可能です。本記事では、その手順を説明します。


## 手順

1.　コミット履歴を確認する

まず、どのコミットに戻すかを決めるために、git log で現在のブランチにあるすべてのコミット履歴を表示させます。

- コード
    
```bash
git log
```
    
- 想定される実行結果
    
```bash
% git log
commit <コミット番号> (HEAD -> main, origin/main, origin/HEAD)
Author: Your Name <Your Address>
Date:   Wed Sep 11 11:59:40 2024 +0900

    <コミットメッセージ>
% 
```

2.　ローカルの変更を破棄する

ローカルの変更をすべて破棄して、ワーキングツリーをまっさらな状態に戻します。
git reset --hard で、すべてのローカル変更を取り消します。

- コード
    
```bash
% git reset --hard
```
    
- 想定される実行結果
    
```bash
% git reset --hard
HEAD is now at <コミット番号やコミットメッセージ>
% 
```

3.　特定のコミットに戻す

次に、特定のコミットに戻すためには、git reset --hard <コミット番号> コマンドを使用します。これにより、そのコミットの状態にリセットされます。

- コード
    
```bash
% git reset --hard <コミット番号>  ## 特定のコミットに戻す
```
    
- 想定される実行結果
    
```bash
% git reset --hard <コミット番号> 
HEAD is now at <コミット番号やコミットメッセージ>
% 
```

以上が、ローカルの変更を破棄して特定のコミットにリセットする手順です。
git reset 系は、慎重に使ってください。
How to Pass the AWS DOP-C02 Exam

![DOP-C01-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442951/5e0226e0-f493-e0d1-58c6-70b2a75a534a.jpeg)

https://awslagi.com/course/aws-certified-devops-engineer-professional-dop-c02-actual-exam/

## Affordable & Updated Course on Our Website

Are you preparing for the **AWS Certified DevOps Engineer - Professional (DOP-C02)** exam? Look no further! We’ve just released a **comprehensive, affordable, and frequently updated course** to help you succeed. Whether you’re looking for hands-on practice, in-depth theoretical knowledge, or exam-specific tips, this course will guide you every step of the way.

### Key Features of Our Course:
- **Low Price**: We believe in quality education at an affordable price, so you can access all the resources without breaking the bank.
- **Updated Frequently**: AWS services are constantly evolving, and so are our course materials. Our team ensures the content stays relevant to the latest exam objectives.
- **Real-World Scenarios**: Learn how to apply AWS best practices in actual DevOps environments.
- **Exam-Specific Practice**: Get familiar with the AWS DOP-C02 exam format with tailored practice questions and mock exams.
- **Detailed Explanations**: Understand the reasoning behind each question with detailed explanations and solutions.

### Why Choose This Course?
The **AWS DOP-C02** is a challenging exam, but with the right preparation, passing it is within your reach. Our course covers all the important topics, including:
- **Continuous Delivery and Deployment**  
- **Monitoring and Logging on AWS**  
- **Security and Governance**  
- **Infrastructure as Code (IaC)**  
- **Automating AWS Services**  

### Benefits of Becoming AWS Certified
- **Career Advancement**: AWS DevOps certification validates your skills, opening doors to higher-paying jobs and career advancement.
- **Industry Recognition**: Gain global recognition as an AWS professional.
- **Increased Knowledge**: Master key AWS tools and services, from CloudFormation to CodePipeline.

### Start Your Journey to Success Now!
Visit our website today to enroll in the **AWS DOP-C02 course**. Prepare confidently with the right tools, resources, and expert guidance. Don’t wait – **boost your career** with an AWS certification today!
基本的なURLについての用語

## アジェンダ
基本的なURLについての用語を備忘録的にまとめます。

## URLとは
URL（Uniform Resource Locator）は、ウェブ上のリソース（ウェブページ、画像、動画など）の場所を指定するアドレスのことです。インターネットブラウザがリソースを取得するために使われます。

## URLの書式
URLは以下の形式で構成されます：  
```
プロトコル://ホスト名（ドメイン）/パス?クエリ#フラグメント
```
- **プロトコル**: リソースへアクセスするための方法を指定します（例: HTTP, HTTPS）。
- **ホスト名（ドメイン）**: リソースが存在するサーバーの場所を指定します（例: www.example.com）。
- **パス**: サーバー内でリソースがどこにあるかを示します。
- **クエリ**: リクエストに追加の情報を提供します（例: `?id=123`）。
- **フラグメント**: 特定のページ内の部分を指定します（例: `#section`）。

## ドメイン、サイト、オリジン
- **ドメイン**: ウェブサイトが存在するサーバーを特定する名前です。例として `example.com` は1つのドメインです。
- **サイト**: ドメイン内で公開されているウェブページやリソースの集合体です。
- **オリジン**: プロトコル、ドメイン、ポート番号の組み合わせで、あるウェブリソースのセキュリティコンテキストを表します。

## クロスオリジンアクセス
クロスオリジンアクセスとは、1つのオリジンから別のオリジンにあるリソースへアクセスすることです。セキュリティ上の理由から、ブラウザは異なるオリジン間でのリソース共有を制限しますが、CORS（Cross-Origin Resource Sharing）ヘッダーを使用することで、これを許可できます。

## 参考
- [CORS in 100 Seconds - YouTube](https://www.youtube.com/watch?v=4KHiSt0oLJ0&ab_channel=Fireship)
組織図や組織情報をどのように取り扱うか

非ITのバックオフィスが頑張るシリーズです。
今回は組織図のお話です。
## 組織構造のDB設計について
### 組織図の標準フォーマット？
組織図を表現するフォーマットって標準化されたもの、あるんでしょうか？
Excel、PowerPoint、Visio、Wordあたりでゴリゴリ書くのが一般的なんですかねえ。
複数のSaaS製品を使用していると、組織図（組織情報）の設定が必要で、それぞれフォーマットも違います。
組織構造がDBにあって、それをベースに組織図が自動で作成されたり、各種SaaSのインポート用フォーマットを出力できたり、API連携できたらいいですよね。
MarkdownのMermaid記法とかだとデータベースと相性が良さそうな気もします。
### As Is
当社の場合はPowerPointで作成した組織図を元に、各種データを手作業で作成しています。
1. PowerPointで作成した組織図
1. PowerPoint組織図を見ながらカオナビ用の所属情報csvに手作業で変換
1. カオナビ用csvからfreee人事労務の部門一括インポート用csvに変換（わりと手作業）
1. PowerPoint組織図を見ながらKickflowの組織図csvに手作業で変換
### To Be
* DBに組織情報、人事情報が格納されている
* DBから組織図（PowerPoint他複数フォーマット）を出力できる
* 各種SaaSインポート用の組織情報CSVファイルが出力できる
* 各種SaaSと組織情報をAPI連携できる
### 組織図をDBで表現する
当社には社内用のRDBがありません。100人程度の会社ですし、RDBを持つのは管理コストのほうが大きい気もしますので、いったんGoogleスプレッドシートをDBとして作成していきたいと思います。
とはいえ、将来的にRDBに移行できるように、ある程度将来を見据えた設計にしていこうかと考えています。
シートをテーブルとし、スプレッドシート全体でひとつのDBとなるようなイメージです。
ではどのようにテーブル設計をしたらよいでしょうか。
### テーブル設計
ちょうど良い記事を見つけましたので、参考にさせていただきました。
[組織図をデータベースで表現する](https://blog.nextscape.net/archives/2021/12/14/000000)（ネスケラボ）
なるほど、「組織図など木構造のデータをDBに登録する際は、階層問い合わせを使用する構造にしよう」ということなんですねー。履歴系のカラムはもう少し検討する必要がありそうですが、いったんこの形のテーブルにしてみましょう。

| ID | GroupName | ParentID | LeaderId | HistoryId
|:-----------|:------------|:------------|:------------|:------------|
| 組織ID     | 組織名| 親組織ID | リーダーID|履歴ID|

まずはこの情報だけあれば、組織の木構造が登録でき、各種SaaS用のCSVは作れてしまいそうです。
当社の場合は[Kickflow](https://kickflow.com/)のCSVがこの形式に近いので、逆にここからインポートしてDBを作成してみます。
2024年9月版 AWSサービスからAI学習をオプトアウトする方法〜ボタンポチポチで終わりに〜

簡単になりました
クリックポチポチだけです

>すべての AI サービスをオプトアウトするには
AWS Organizations コンソール にサインインします。組織の管理アカウントで、 IAM ユーザーとしてサインインするか、 IAMロールを引き受けるか、ルートユーザー (推奨されません) としてサインインする必要があります。
AI サービスのオプトアウトポリシーページで、すべてのサービスからオプトアウトを選択します。
すべてのサービスからオプトアウト ページで、すべてのサービスからオプトアウト を選択します。

https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_ai-opt-out_all.html



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37384/73637836-7114-2e82-5d27-8c4b3aecf8b0.png)

↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37384/d1f85361-dd95-e4dc-213a-bcaf71efc52e.png)

実行することで自動的にrootにscpポリシーが追加されます。
通常のSCPポリシーとは別管理のようで、SCP画面からは見えません。

(もしMonitoronを使っていたら追加手順を踏みましょう)


簡単になったというより以前の方法はポリシー自作など手順が多過ぎでしたね
期待通りになりました
【ChatGPT＋Code Interpreter】で画像内のパネルに画像を貼ります。


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

　今回は、画像内のパネルに画像を貼ります。昨日の文字入れの応用です。

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

　ニュースはないので、
　　さっそく本題です。

　今回は、昨日（2024/09/10）の
　　パネルへの文字入れの応用で、
　　　パネルへの画像の組み込みを
　　　　行ないます。
[【ChatGPT＋Code Interpreter】で画像のパネルに文字列を描画します（改訂版）](https://qiita.com/kabumira/items/aee2a767a7c6524d7a7f)

　実際に
　　出来上がった画像がこちら。
![result_image_with_insert.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/df0dab69-d8b1-4ebe-7db4-c9a376b9c274.png)

　まぁ、
　　パネルの上に、絵がある
　　　みたいに見えるので
　　　　もう少し微調整が
　　　　　必要なのですが😅

　では、はじめましょう。
　　今回は、文字入れではないので
　　　フォントの読み込みは
　　　　ありません。

　手順は
　❶GPT-4oであることを確認
　❷ふたつの画像をアップロードして
　　　下記Promptを送信
```Text:画像読み込みPrompt
最初の画像を元画像とします。
二番目の画像を組み込み画像とします。
```
　❸下記Promptを送信
```Text:画像内のパネルに画像を組み込むPrompt
# 画像内のパネルに画像を組み込む

### 使用するライブラリ：
PillowとSciPyを使ってください。

### 処理の詳細
1. **画像の読み込み**：
   - Pillowを使用して、指定された元画像をRGB形式で読み込みます。

2. **白色の定義**：
   - 「白色」は、RGB値がそれぞれ210以上のピクセルとして定義します。

3. **白色領域の検出**：
   - SciPyを使用して、白色のピクセルで構成される領域（連続したピクセルのグループ）をすべて検出します。

4. **最も大きな白色領域の選択**：
   - 検出された白色領域の中で、ピクセル数が最も多い領域を特定します。

5. **画像のリサイズ**：
   - Pillowを使用して、最も大きな白色領域に収まるように取り込み画像のアスペクト比を保持したまま縮小します。白色領域の幅と高さに合わせて、画像の縦横比を保ちながら適切にリサイズします。

6. **画像の描画**：
   - リサイズされた取り込み画像を、Pillowを使用して白色領域の中央に配置します。

7. **結果の保存**：
   - 取り込み画像が描かれた元画像をPillowを使って保存します。
```
　❹ダウンロードリンクが表示

　これで、
　　出来上がります。

　前回から若干、
　　Promptを変更してあります。
　　　これはChatGPTさんと
　　　　さんざんやり取りした内容で
　　　　　修正してもらった結果です。

　もちろん、
　　新しくセッションを
　　　開いて、試してあります。

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

　今回は、ここまで。
AWS 「Prompt Flows」S3 Storageノードを使って、テキストファイルをS3に保存＆上書きしてみた

# はじめに
今回はAmazon Bedrock「Prompt Flows」のS3 Storageノードを使って、入力したテキストをS3の指定した場所に保存するアプリケーションを作成してみました。

「Prompt Flows」は、ノードを配置して生成AIのワークフローを開発・管理できるサービスです。

https://aws.amazon.com/jp/bedrock/prompt-flows/

# 導入
アプリケーションの全体像は以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/029b0af4-c0a9-1f71-59c7-1cea75c825b7.png)

**①コンテントとオブジェクトキーの入力**
**②S3の指定された場所への保存**
**③S3格納URLパスの出力**
という流れになっています。

アプリケーションの流れについて説明します。

**①コンテントとオブジェクトキーの入力**

コンテント(保存したいテキストの内容)と、オブジェクトキー(保存したいオブジェクトの場所)をJSON形式で入力します。
そのため、TypeではObjectを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/ebf70cb9-6f8b-741a-4c16-dafc30f13c32.png)


**②S3の指定された場所への保存**

**①**で入力したコンテントを、S3のオブジェクトキーのある場所に保存します。
まず使用するバケットを指定します。
JSON形式のデータを指定するために、Expressionには、
$.data.content
$.data.objectKey
と入力します。

Outputでは、S3格納URLパスを出力します。

![s3s_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/1d7fde55-3f8a-1f3c-803f-02b5f89e6678.png)


**③S3格納URLパスの出力**
**②**で出力されたパスを、フローの最終結果として出力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/29bbc724-eec7-589f-0697-e8c8412d8733.png)


# 実行結果
今回の実行例は以下の通りです。

・記入例
```
{
  "content": "This is test",
  "objectKey": "folder3/AWS.txt"
}
```

Prompt Flows上では、テキストが保存された、S3格納URLパスが出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/b33679f7-9973-0bac-578a-0681cd2f8a10.png)

S3上では、指定した、folder3の中に、AWS.txtが保存されていることが確認できます。

![s3s_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/ef769d38-0904-28f1-0d9a-9eae33b20ff8.png)

また、AWS.txtの中身を確認すると、入力した通り、This is test と表記されています。

![s3s_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/2dd5ffc0-dab1-084b-ab0d-049b22f7b108.png)

さらに、同じオブジェクトキーで違うコンテントを入力すると、上書きをすることも可能です。
```
{
  "content": "Hello, this is the test of S3 node.",
  "objectKey": "folder3/AWS.txt"
}
```

![s3s_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/9f9fd087-5348-249a-1003-5cba8f64a766.png)

# まとめ
今回は「Prompt Flows」のS3 Storageノードを使って、入力したテキストをS3の指定した場所に保存するアプリケーションを作成してみました。
今後はもっと発展した内容の例を作成したいと考えています。
2024　Microsoft Azure Bootcamp　生成 AI 2.0 -日本の導入実例とトレンドから学ぶ生成 AI ビジネス活用

## はじめに
本記事では、Microsoftのイベント「Azure Bootcamp 2024」にて行われた「生成 AI 2.0 -日本の導入実例とトレンドから学ぶ生成 AI ビジネス活用」についてまとめた記事です。
## 公式ページ
[公式ページへのリンク](https://www.microsoft.com/ja-jp/events/jpazurebootcamp/?msockid=06a7da68f35f60bf1072ceb2f2e8614d)
## SLM(small language model)について
### LLMではなくSLMを使うメリット

 - __サイズに対しての品質とコスト優位性がある：__ SLMは小規模モデルながら、高品質な結果を提供するこれによりトレーニングコストや運用コストが軽減される
 - __利用するデバイスを選ばない：__ SLMは軽量であるため、エッジデバイスやモバイルデバイスでも容易に利用可能
 - __パフォーマンス、推論スピードが速い：__ 小規模なモデルであるため、推論速度が速く、リアルタイムの応答が可能
 - __長文プロントの挿入、ファインチューニングが容易：__ SLMは特定のタスクに対して簡単にカスタマイズでき、長文のプロンプトにも対応可能 

利用イメージ
 - 固定タスク用のAI：例えば、特定の質問に対する回答を提供するチャットボット等
 - オンデバイスにて利用：モバイルアプリやIoTデバイスでの利用

### SLMとLLM比較
|特徴|LLM|SLM|
|:--:|:--:|:--:|
|モデルサイズ|非常に大規模<br>（数十億～数千億パラメータ）|小規模<br>（数百万～数億パラメータ）|
|学習データ|膨大かつ多様な<br>データセットを使用|限定された特定の<br>データセットを使用|
|コスト|トレーニングと運用コストが高い|トレーニングと運用コストが低い|
|適用範囲|汎用的なタスクに<br>広く適用可能|特定の用途やドメインに特化、<br>エッジオフラインでも適用可能|
|パフォーマンス|応答速度が遅くなる場合がある|迅速な応答が可能|
|デプロイの<br>容易さ|複雑で専門的な知識が必要|比較的簡単で一般的な<br>知識で可能|


## multi modal
AIが複数の情報をもとに考え結果を出力する方式
音声、テキスト、画像等
 
## multi model
用途別で複数のモデルを使い分ける方式
またAzure AI モデルカタログには1700以上のモデルがあり大きく下記3つに分類される
 - LLM：汎用型
 - SLM：業種等の特定事項特化型
 - LM：言語特化型

　2024年11月以降、日本語特化モデルのNTT DATAのtsuzumiをクラウド上で
 　利用可能予定
## multi modal利活用
コールセンターでの利用

リアルタイムの会話音声から下記内容を出力することができる
 -  __レポート作成__
 -  __json形式の構造体でファイルを出力__
 -  __会話内容からAIが推論し、オペレータに助言をする__

これによりコールセンターの品質が安定し、顧客の待ち時間が短縮される。また、AIがオペレーターにリアルタイムで助言を提供するため、管理者の手が空いていない場合でも迅速に対応が可能。これにより、オペレーターと管理者の両方が焦ることなく、スムーズに案内を行うことが可能

## 日本独自の活用事例（自動車メーカー）
 __SLMの活用：__
 - 走行中のサポート： SLMは走行中に発生する出来事やスピードに基づいて車両マニュアルを検索し、運転手に助言を行う
 - 運転シーン分析：時間、明るさ、天候、対向車の有無、路面状況等から状況を整理し分析を行う


__OpenAIとの連携：__
 - 大規模な検索: カーナビなどで大規模な検索が必要な場合、OpenAIに接続して処理を行う。例えば、「この辺にどんなエンタメ施設があるか提案して」といった問いかけに対して、OpenAIが提案を行う
 - パーソナライズされた提案: 事前に家族情報を登録しておくことで、より状況に沿った回答を提供する


## まとめ
SLMは小規模なモデルながら高品質な結果を提供し、トレーニングや運用コストを削減できる点が特徴。また、軽量であるためエッジデバイスやモバイルデバイスでも容易に利用可能で、推論速度も速くリアルタイム応答が可能。さらに、特定タスクへの適応や長文プロンプトの対応が簡単であるため、カスタマイズが容易

次に、SLMとLLMの比較について。LLMは非常に大規模で膨大かつ多様なデータセットを使用する一方、SLMは小規模で限定された特定のデータセットを使用する。LLMはトレーニングと運用コストが高いのに対し、SLMは低コストで済む。また、LLMは汎用的なタスクに広く適用可能であるが、SLMは特定の用途やエッジオフラインに特化している。パフォーマンス面では、LLMは応答速度が遅くなるのに対し、SLMは迅速な応答が可能。デプロイの容易さにおいても、LLMは複雑で専門知識が必要だが、SLMは比較的簡単


さらに、multi modalとmulti modelについて。multi modalは音声、テキスト、画像など複数の情報をもとに結果を出力する方式であり、multi modelは用途別に複数のモデルを使い分ける方式。Azure AIモデルカタログには1700以上のモデルがあり、LLM、SLM、LMに分類される


具体的な利用事例として、コールセンターと自動車メーカーのケースを紹介。コールセンターでは、リアルタイムの会話音声からレポート作成やオペレータへの助言を行い、品質向上と顧客待ち時間の短縮を実現している。自動車メーカーでは、走行中のサポートや運転シーンの分析にSLMを活用し、OpenAIとの連携で大規模な検索やパーソナライズされた提案を提供している
＃50　Windows版LINEの改行/送信設定を変更する方法

## 概要

Windows版のLINEは、Shift+Enterで改行、Enterで送信ですが、他チャットツールで慣れ親しんだ改行設定と統一させたかったので、Enterで改行、Ctrl+Enter で送信になるようカスタムしました。
その手順を解説します。

## 手順1: Enterを改行にする

一応、LINE公式でも改行設定を用意してくれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3843084/6530e6f4-6370-eba2-8468-f67557969056.png)

設定→トーク→送信方法 の欄が、デフォルトだと「Enter」になっていますが、
ここを「Alt + Enter」に設定すると、Enterが改行、Alt + Enterで送信になります。
Alt + Enter で送信でよい人はこれだけでOKです！
私の場合は、Ctrl + Enter で送信したいのでもう少し手を加えます。

## 手順2: Ctrl + Enter を Alt + Enter にリマップする

ざっくりと書くと、LINE起動中に Ctrl + Enter が押されたとき、コンピュータにAlt + Enterが押されたと勘違いしてもらいます。
これには、[AutoHotkey](https://www.autohotkey.com/) というフリーソフトを使います。
こちらはスクリプトを書くことでキー入力を自由にカスタマイズできるソフトで、Windowsでキーカスタマイズをするときの定番の選択肢の一つです。

公式サイトからインストーラーをダウンロードしてインストールしましょう。

続いて、実行するスクリプトを用意します。
`lineCustom.ahk`というファイルを作って、中身にこのように書いてください。
※ファイル名はなんでもよいですが、拡張子は.ahkにする必要があります
```plaintext:lineCustom.ahk
#SingleInstance force ; スクリプトの多重起動防止

#IfWinActive,ahk_exe LINE.exe ; LINEを開いているときだけ
^Enter::!Enter  ; Ctrl + Enter を Alt + Enter に置き換える
#IfWinActive
```
あとは、作成したこの `lineCustom.ahk` をクリックして実行するだけで、
LINEが Ctrl + Enter で送信できるようになるはずです。
※ちなみに、Alt + Enter の抑止を入れていないのでAlt + Enter でも送信されます。

## 手順3: AutoHotkeyファイルをスタートアップに登録する

手順2で作成した `lineCustom.ahk` ですが、このままだとPCを起動したときに毎回手動で実行しないといけません。
そこで、スタートアップに登録して、PCが起動したときに自動で `lineCustom.ahk` が実行されるようにします。
まず、エクスプローラーのアドレスバーに`shell:startup`と入力してEnterを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3843084/3235ad63-ad69-8f58-81b2-815df82703bc.png)

すると、スタートアップのフォルダに遷移するので、`lineCustom.ahk`をここに移動します。
これで、PC起動時に自動で`lineCustom.ahk`が実行されるようになります。

以上で完了です。

## 最後に
[以前の記事](https://qiita.com/nxted_sapporo/items/4b9364dda2c0a2c58d0a)でGoogle Chatの改行設定を変更しましたが、今回はLINEの改行設定を変更してみました。
やりたいことは一緒でしたがアプローチが違って面白いですね。
実はDiscordの改行設定も気になっているのですが、今回のLINEの対応からもう一工夫必要な気がしているので、
気が向いたらやってみようと思います。
最後まで読んでいただきありがとうございます。

## 参考

https://ahkwiki.net/Top
https://www.naporitansushi.com/autohotkey-startup/
gitlab: header機能でメンテナンスの通知

# header機能でメンテナンスの通知

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/614c63dd-5b02-a992-6bcf-053f63b5a1cf.png)


## 手順

!!!Admin権限が必要です!!!

Admin Area -> Settings -> Appearance -> System header and footer
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/e54aba03-bae9-03c6-e93e-8ca986d0e8ba.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/c4cdbd85-a9fa-bf88-cbf4-91f87efc0273.png)


```html
<div style="background-color: #f0f0f0; padding: 20px; text-align: center; height: 100px;">
  <a href="https://example.com" target="_blank" style="color: #007bff; text-decoration: none;">
    メンテナンスのお知らせ
  </a>
</div>
```
jupyterでpdやplのDataFrameを1行が1Lineになるようdisplayさせる(折り返し・改行抑制)

[241008 コピペミスって一部変数が機能していなかったなどについて修正]

plやpdのdfをjupyterでdisplayした際に、
日本語の自動折り返しがめちゃくちゃで行高がえらいことになって
イライラすることが度々あったので、対応関数を作成してみた。
`white-space: nowrap !important;` を与えることで、
セル内での改行/折り返しを抑制させている。
pandasに限れば `d1.to_pandas().style.set_table_styles([{'selector': 'td', 'props': 'white-space: nowrap !important;'}])` という手もあるが、
これはpd.optionのmax_colwidthでは制御できず、
改行/折り返し無しだと横にとんでもない長さとなることがあるため却下。


```python
from IPython.display import display_html
import pandas as pd
import polars as pl
import datetime

def display_df(df, max_rows = 30, max_strlen = 50):
    """
    plかpdのDataFrameをセル内改行を抑止してdisplayする。
   
    Args:
      df (pl.DataFrame|pd.DataFrame|dict): plかpdのDataFrame
      max_rows (int): 表示させる最大行数 (これ以上だと間に...が入る)
      max_strlen (int): 表示させる最大文字数 (これ以上だと...になる)

    """
   
    tbl_id = "T_" + datetime.datetime.now().strftime("%m%d%H%M%S%f")
    new_style = '<style type="text/css">\n#' + tbl_id + ' td, th {\n  white-space: nowrap !important;\n}\n</style>'
       
    with pd.option_context("display.max_rows", max_rows, "display.max_colwidth", max_strlen + 1):
        with pl.Config(tbl_rows = max_rows, fmt_str_lengths = max_strlen):
            raw_html = df._repr_html_()
           
    html_ = re.sub("<style.*?</style>", new_style, raw_html, flags = (re.MULTILINE | re.DOTALL))
    html_ = re.sub('<table', f'<table id="{tbl_id}"', html_, 1)

    display_html(html_, raw = True)  
    pass
```


example:
```python
d1 = pd.DataFrame({"aa": ["aaaaaaaaaaaaaa"],
                   "bb": ["日本語の文字はうまく折り返されない。"],
                   "cc": ["aaaaaaa bbbbbbbb"], 
                   "dd": ["aaaaa bbbbbbbb cccccccc"],
                   "ee": ["aaaaaaa bbbbb cccccccc dddd"]})
display(d1)
display_df(d1)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234930/c10ac827-a029-eab9-c32f-1ec0af5acf2d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234930/8ab7c941-dd9e-0acc-eeaa-9bb32558a37b.png)