OmniAICreator/Qiita-1.07M huggingface dataset:
Xcode - Swiftでおみくじアプリを作成しました

Xcode - Swiftで簡単なおみくじアプリを作成しました
以下、一部ソースを掲載します

```Swift:SecondView.swift
import SwiftUI

struct SecondView: View {
    // おみくじ結果を保存する変数
    @State private var result: String = "おみくじを引いてね！"
    
    // おみくじの結果の候補
    let omikujiResults = ["大吉","中吉","小吉","末吉","凶"]
    
    var body: some View {
        VStack(spacing: 20) {
            Text("これは2ページ目です！")
                .font(.largeTitle)
                .padding()
            
            Text(result) // 結果を表示するテキスト
                .font(.largeTitle)
                .padding()
            
            Button(action: {
                // ボタンが押された時の動作
                result = omikujiResults.randomElement() ?? "エラー"
            }) {
                Text("おみくじを引く") // ボタンの表示テキスト
                    .font(.title)
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
            
            // リセットボタン
            Button(action: {
                // 結果を初期値にリセット
                result = "おみくじを引いてね！"
            }) {
                Text("リセット")
                    .font(.title)
                    .padding()
                    .background(Color.red)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
        }
        .padding()
    }
}

struct SecondView_Previews: PreviewProvider {
    static var previews: some View {
        SecondView()
    }
}
```

まだiPhoneアプリを作成し始めたばかりなので
わからない点も多いですが
今回いくつか学びがありました

### 今回の学び①
SwiftUIで画面遷移を実現するには、親ビューをNavigationViewでラップする必要がある。

### 今回の学び②
@State変数とは何か？
@StateはSwiftUIで使われる「データの状態管理」に関する仕組みである。
ビューがユーザーの操作やアプリの動作で変化する場合、
@Stateを使ってその変化を追跡し、ビューを自動的に更新する。

以上です。
Excelアドインの作り方 ～リボンUIで実装～

記事作成途中につきメモ書き形式です。すみません。
# Excelアドインの作成方法
Excelアドインを作成し、リボンUIを実装するための備忘録です。
インターネット上のフリーソフトは使用できない環境向けの、メモ帳さえあればできるやり方です。

## 手順

Excelでマクロ入りブックを「Excelアドイン（xlam）」として保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513605/4badeff2-f213-4461-3fba-ca81b93aba46.png)


.xlamファイルの拡張子を.zipに変更して解凍ツールで解凍する。

## 中身を編集
CustomUI

### \\_rels\\.rels


```xml:.rels
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship Id="R62314067f168429b"
        Type="http://schemas.microsoft.com/office/2007/relationships/ui/extensibility"
        Target="customUI/customUI14.xml" />
    <Relationship Id="rId3"
        Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
        Target="docProps/app.xml" />
    <Relationship Id="rId2"
        Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
        Target="docProps/core.xml" />
    <Relationship Id="rId1"
        Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
        Target="xl/workbook.xml" />
</Relationships>
```


### \customUI\customUI14.xml

```xml:customUI14.xml
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
	<ribbon startFromScratch="false">
		<tabs>
			<tab id="Tab01" label="Tab01">
				<group id="Group01" label="Group01">
					<button id="Button01" label="Button01" imageMso="Info" size="large" supertip="これは説明文です。" onAction="test.xlam!Callback" />
					<button id="Button02" label="Button02" imageMso="Help" size="large" onAction="test.xlam!Callback" />
				</group>
			</tab>
		</tabs>
	</ribbon>
</customUI>
```

ファイルを作成し、上記の記述が終わったら保存。

再度zipに圧縮（_relsとかdocPropsとかのフォルダ階層で圧縮しないとダメ）して、
拡張子をxlamに戻す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513605/f47c0eb7-9f5d-3c10-d253-37b5da8ef80c.png)

C:\Users\[ユーザー名]\AppData\Roaming\Microsoft\AddIns
フォルダに上書き保存。
AWS-CLFぎりぎり合格

## CLFを1週間以内に合格

現在、AIF、CLFが2025年2月15日まで再受験が無料のキャンペーンを実施していたのでCLFを受験してきました！
以下は現在キャンペーン中のURLです！
[AWS Foundational 認定試験の再受験無料](https://pages.awscloud.com/GLOBAL-other-GC-traincert-aws-foundational-certification-2024-learn-jp.html)

### 学習方法
CloudTechの資格演習

### 学習時間
合計時間: 40時間
短期決戦型の勉強スタイルでした。

#### 私のスペック
学歴: F大卒（文系、非情報系）
経歴: 防人 → ロースキル系SES（2年目）
保有資格: CCNA、LpicLevel1、AZ900（取得から1年経過）
クラウドの知識含め、全く内容を覚えていませんでした。

#### なぜ受験するのか
・転職を見据えてスキル証明が必要と感じたため。
・AWS認定資格の取得でやる気を出すきっかけに。
・半額クーポンがもらえる特典も後押しに！

### 勉強の流れ
・CloudTechの資格演習を解きまくる
1周目は解説を理解しながら進め、2周目で間違えた箇所を重点復習しました。

### まとめサイトを活用
[「[AWS]残り2日間でCLFの合格へ- これ抑えとこ！まとめてみた(10日で合格！)」](https://zenn.dev/airiswim/articles/24552ec0962749#%E7%AC%AC-1-%E5%88%86%E9%87%8E%3A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%81%AE%E3%82%B3%E3%83%B3%E3%82%BB%E3%83%97%E3%83%88)がとてつもなく参考になりました。

結果　714点
![スクリーンショット 2025-01-16 210914.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332715/10e493d4-8526-89d4-b4f5-5b75ab204aa4.png)

という感じでぎりぎりでした。※1問が20点なので、合格ライン(700点)の真上です。
もっとしっかり事前に情報収集していればと後悔しています。

### 試験前に知っておけばよかったこと
以下は余裕をもって合格するために、参考にしてください。
・ホワイトペーパーを読む（Well-Architected FrameworkとCAF）
・[「AWS Skill Builder」無料版](https://explore.skillbuilder.aws/learn/external-ecommerce;view=none;redirectURL=?ctldoc-catalog-0=l-_ja~se-CLF)

・[AWS Cloud Practitioner Essentials (日本語) 動画(7時間)](https://explore.skillbuilder.aws/learn/courses/1875/aws-cloud-practitioner-essentials-ri-ben-yu)

上記存在に気付いたのは試験の前日！

### 最後に
CLFの取得は誰にでも取得可能な資格です。
基礎的な知識をインプットし、問題集を繰り返し解くだけで十分合格できます。
時間をかける余裕があれば、さらに理解が深まり余裕をもって挑むことができるでしょう。

この記事が、これからCLFを目指す方の参考になれば幸いです！
ご覧いただきありがとうございました！
【AWS SAP】Snowball比較表

| **名前**                     | **容量**     | **計算機能**       | **用途**                             |
|------------------------------|-------------|--------------------|-------------------------------------|
| **AWS Snowcone**             | 8TB          | 簡単な計算が可能     | 小規模プロジェクトや軽量作業          |
| **AWS Snowball Standard**    | 約50～80TB   | なし                | データ転送のみ                       |
| **AWS Snowball Edge Storage**| 最大100TB    | 基本的な処理が可能   | 大量データの保存・転送               |
| **AWS Snowball Edge Compute**| 最大100TB    | 高度な計算が可能     | AI・機械学習・エッジコンピューティング |
gitって凄いですね！基本操作の名称

# 前回までの掲示板

前回の掲示板作成では、`$slot`が定義されていなくて、ずっとGPTがループしてしまった。

こういう時、理解が浅いと解決までが不明になるなと痛感。  
そんな時に**Cursor**を利用して何回か試したら解決した。  
結局、「定義しないで使わない方針で行こう」ということになり、無事に解決。

その後はUIを**Bootstrap**で書いていた。  
このプロジェクトの途中から使い始めたのが**Git**。

自分の中で革命が起きたのがこの**Git**。  

「これ、なんで今まで教えてもらえなかったんだろう？」と思うくらい便利で驚いた。

---

# いきなり出てきたGitと気になっていたGitHub

GitとGitHub、前から名前は聞いていたけど、正直よくわかっていなかった。  
今後絶対必要だから「使ってみよう」ということになり、触りながら学ぶことにした。

~~Gitはローカル（自分のPC）で使うもの~~
~~GitHubはそのデータをリモート（クラウド上）で管理するサービス。~~

Gitはソースコードのバージョン管理ツール。
GitHubはgit(ツール)のリモートの保管場所の一つであり、
便利に使うためのWebサービス。


Git単体でもリモートリポジトリがあることは少し認識がズレていた気がします。

この２つの関係性はGitでリモートリポジトリとして保管する場所をGitHubにする。

そのGitHub上のサービスを使ってチームで開発したりするようです。

GitHubの特徴にプルリクエストがあった。
コードの変更を他のメンバーにレビュー依頼を出せる機能。
そこでOKが出たものだけがコードに反映される仕組みだ。


参考にした記事
[今さら聞けないGitとGitHubの違いって何？]
https://www.i3design.jp/in-pocket/3111


実際の作業では、コマンドよりも**Sourcetree**を使ってGitとGitHubを操作している。

![スクリーンショット 2025-01-16 23.49.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3978958/30348ddd-d17a-fc0c-eaaa-e3d881c27e10.png)


## バージョン管理システムの認識間違ってた！
バージョン管理とは、ソースコードやドキュメントの変更履歴を保存し、変更を追跡したり、以前の状態に戻したりする仕組みのこと。

これが本来の「バージョン管理」の意味だった。

勘違いしていたのは、フレームワークやライブラリのバージョンを管理して、チーム全体で同じバージョンを使えるように環境を構築することが「バージョン管理」だと思っていたこと。

↑これは正確には「依存関係のバージョン管理」と呼ばれるもので、結果的にGitでその設定を管理することも可能。だから完全に間違いではないけれど、バージョン管理システムの本質はもっと広い意味だった。


---

# GitとGitHubの概念を整理

Gitの仕組みを自分なりに整理すると、こういうことだと思う。

1. **リポジトリ**という保管箱がある。  
   ~~ローカル（自分のPC）とリモート（クラウド上）の2種類がある。~~
   Gitにはローカル（自分のPC）とリモート（別のサーバー）の2種類がある。
2. ~~リモートのリポジトリを管理するのがGitHub。~~
Gitのリモートのリポジトリの保管場所をGitHubというWebサービス上に置く。

ローカルでの作業はこんな感じ。

- **メインブランチ**を基準にして動かす。
- **main**から**developブランチ**を作って、ここを主軸に開発を進める。
- **develop**から機能ごとにブランチを切って作業する。
- 開発が終わったら**マージ**して**develop**に統合する。

本来ならレビューのためにプルリクエストをするみたいだけど、今回は一人なのでスキップ。

git内での作業が終わった後の流れはこんな感じ。

1. **ステージング**: 変更したファイルの中から、リポジトリに記録するファイルを選ぶ。
2. **コミット**: ステージングエリアの変更をリポジトリに記録する。
3. **プッシュ**: ローカルの変更をリモートリポジトリ（GitHub）に反映する。

---

# 感想

Gitの一番便利だと思ったのは、機能ごとにブランチを分けて作業できること。  
もし失敗しても、過去の状態に戻れる安心感がすごい。  

ブランチを消さなければ、そのまま続きから作業を再開できるのも便利。

これまで(別の会社の職種で)は、エクセルの修正や改修のたびに「ファイルをコピーしてV2、V3」と増やしていたけど、Gitならその必要がない。
なんなら過去なんていらない全て上書きしていけーという人もいたので大変だった。

コミットした地点さえ記録しておけば、いつでもその時点に戻れるのが最高。  

もっと早く知りたかったな。

---

# 用語まとめ

忘れそうなので、自分用に用語を整理しておく。

### リポジトリ
- プロジェクトのファイルや履歴を管理する保管箱。
  - **ローカルリポジトリ**: 自分のPC上にあるリポジトリ。
  - **リモートリポジトリ**: ネット上にあるリポジトリ。

### コミット
- 変更をリポジトリに記録すること。

### ステージング
- 変更したファイルをコミットする準備をすること。

### プッシュ
- ローカルの変更をリモートに反映する操作。

### プル
- リモートの変更をローカルに取り込む操作。

### フェッチ
- リモートの最新情報を取得するけど、ローカルには反映しない。

### ブランチ
- リポジトリから分岐して作業する単位。  
  「ブランチを切る」とよく言うらしい。

### マージ
- 他のブランチで行った変更を取り込むこと。

### HEAD
- 現在のブランチやコミットの位置を指す。

### origin
- リモートリポジトリのデフォルトの名前。


他にもたくさんあるようだけどメインのパーツを理解しておこう。
理解とできるは違うから早く使いたいものだ！
まじでこの世界楽しいぞ。
AI学習は本当に凄い。(今のところ)

次はドキュメントから制作を始める。
acl の権限は root からも見えないときがある

Ubuntu 22.04 で、少し気になる挙動を見つけた。

YubiKey をユーザ権限で使うにあたり、YubiKey をさしたときに現れる /dev/hidraw2 を見ていたが、この権限が、user session の中から見たときと、Ctrl + Alt + F3 等でコンソールから root login したときで、表示が異なるという状態に。

GUI からログインしている状態で、getfacl をすると、

```
root@ubuntu:~# cd /dev
root@ubuntu:/dev# getfacl hidraw2
# file: hidraw2
# owner: root
# group: root
user::rw-
user:user:rw-
group::---
mask::rw-
other::---
```
ユーザ名が user なので、少しわかりにくいが、user に rw が付与されている。

一方、Ctrl + Alt + F3 で裏にまわり、getfacl した結果がこちら。

```
root@ubuntu:~# cd /dev
root@ubuntu:/dev# getfacl hidraw2
# file: hidraw2
# owner: root
# group: root
user::rw-
group::---
mask::---
other::---
```

裏で GUI にログインしたままだが、/dev/hidraw2 の acl permission が異なっている。
これは一体・・

supplementary group や SELinux で、プロセスのコンテキストから、権限変わることはよくあったが、ファイルを対象に getfacl するようなものまで、変わってしまうんかい、と突っ込みたくなった。

こういうのが隠れていると、root 権限で /dev/hidraw2 の getfacl をみて、アクセス権ないなと思っても、他のコンテキストからは権限持っているみたいなことになってしまう。
これは、さすがに危ないんじゃないか。
【Mac】コマンドでファイルを整理する方法

tidyupを使用することでコマンドを使用してディレクトリ内のファイルを整理できます。

https://github.com/code-env/tidyup

## インストール

以下のコマンドを使用してインストールします。

```terminal
npm install -g tidyup
```

## 拡張子ごとに整理する

拡張子ごとに整理する場合には以下のコマンドを実行します。

```terminal
tidyup /path/to/directory --ext
```

## 作成日ごとに整理する

作成日ごとに整理する場合には以下のコマンドを実行します。

```terminal
tidyup /path/to/directory --date
```
iPad/iPhoneでUSB-C接続のオーディオ機器への音声出力を切り替える方法と対応機種

# 概要
- iPadやiPhoneにUSB-C接続のマイク・イヤホン・スピーカー等を接続したときに、iPadやiPhone本体の音声の再生出力先が強制的に外部デバイスに切り替わり、本体から音声が出せなくなるケースと、本体と外部デバイスのどちらから音声を出力するか選べるケースがあり、何が原因となっているかを調べました。
　
- 再生出力先が切り替えられるケースのメリットとしては、
例えば、**iPadにUSBマイクを接続したときに、マイクから音声入力しつつ、iPad本体で流している音源は本体から出力する**といった動作が可能になります。
  - このときに、外部のマイクの音声自体を本体から出力させたい（＝モニタしたい）場合は、[GarageBand](https://www.apple.com/jp/ios/garageband/)でモニタ:ON、バックグラウンドで実行:ON あたりを設定するのが一番手っ取り早いです。
  - なお、外部デバイスとしてUSBマイクを接続しつつも、素でiPad本体のマイクを有効にする方法は無いと思われます。（アプリの実装で強制的に本体マイクを有効にすることはできるようです。例：[Voistand](https://voistand.com/)）


# わかったこと
- **2022年以降に発売されたiPadでのみ再生出力先を本体に切り替えられることを確認しています。**
  - iPadOS(iPad Pro, iPad, iPad mini)であればどの種類でも対応しているようです。
- iOSは対応していないと思われますが、iPhone Proは未検証です。
- 対応していない機種については、[Audiobus](https://audiob.us/)のようなルーティングアプリを用いても再生出力先を切り替えることはできません。

（もし間違っている点や動作確認した情報などあればコメントいただけると幸いです）

# 再生出力先の切り替え方法（一般的な方法）
1.コントロールセンターの再生中ウィジェットの右上にあるAirPlayアイコンを選択する
（コントロールセンターは、画面の右上隅から下にスワイプすると表示される）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/00ea534d-cf2c-ce62-2b7c-f0d973d77da7.png" width=50%>

2.AirPlayアイコン押下後は、以下のように接続中のオーディオ機器が表示されるので、ここで再生出力先のデバイスを選択する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/c5b6cdaf-5165-0555-eb83-8912eaced22d.jpeg" width=50%>
- 上記画像は、iPad Pro 11-inch(第4世代)に対して、USBでShure MV7を、BluetoothでSRS-XB12を接続した際の様子ですが、**再生出力先の選択ができない機種では"iPad"の選択肢が見えなくなり、USBの接続先とBluetoothの接続先しか選べなくなります。**
- USB接続の際に、オーディオ機器との直接接続でなく何らかのコネクタを用いた場合でも類似の挙動になることを確認しています。

# 再生出力先の切り替え方法（特殊な方法）
- 再生出力先の切り替えに対応した機種では、ショートカットアプリを使い以下のような手順で再生出力先を切り替えることもできます。

1.ショートカットを開く
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/7d4d0027-5dd7-9476-2cb8-efd71ecf5cd1.png" width=10%>

2.新規ショートカット＞メディア＞再生出力先を変更　を選択する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/40e7c969-beb2-a548-da54-212f5e9f3498.png" width=100%>

3.画面上部中央の再生ボタンを押下するか、ショートカットをホーム画面に追加してそのショートカットアイコンをタップする

## （参考）動作を確認した機種一覧

| 機種| 発売年 | OS | チップ | USB | 再生出力先<br>選択可否 |
|:-----------:|:------------:|:------------:|:------------:|:------------:|:------------:|
| iPad Pro 11-inch<br>(第4世代) | 2022 | iPadOS 18.2.1 | Apple M2 | USB 4 | ◯ |
| iPad Pro 12.9-inch<br>(第5世代) | 2021 | iPadOS 18.1.1 | Apple M1 | USB 4 | ✕ |
| iPad Pro 12.9-inch<br>(第3世代) | 2018 | iPadOS 17.6.1 | A12X Bionic | USB-C | ✕ |
| iPad Pro 11-inch<br>(第1世代) | 2018 | iPadOS 17.7.2 | A12X Bionic | USB-C | ✕ |
| iPad (第10世代) | 2022 | iPadOS 未確認 | A14 Bionic | USB 2 | ◯ |
| iPad mini (A17 Pro) | 2024 | iPadOS 18.1.1 | A17 Pro | USB 3 | ◯ |
| iPad mini (第6世代) | 2021 | iPadOS 18.0.1 | A15 Bionic | USB 3 | ✕ |
| iPhone 16 | 2024 | iOS 18.2.1 | A18 | USB 2 | ✕ |
DawarichでGoogleMapタイムラインから脱却しよう

# Dawarich
GoogleMapタイムライン(のようなもの)をセルフホストで動かせるアプリです。
GoogleMapタイムラインからデータをインポートして引き継ぐことができます。

::: note warn
## DawarichでGoogle Map タイムラインからインポートする場合
### 新しいタイムラインについて
2024/06以降の新しいタイムラインに移行している場合、ブラウザのGoogle Takeoutからエクスポートしたデータは`Timeline Edits.json`という編集履歴のデータしかエクスポートできません。
#### インポートする場合
Androidスマホの`設定 -> 位置情報 -> 位置情報サービス -> タイムライン -> タイムラインのエクスポート`から、`タイムライン.json`をエクスポート
WebUIの`Imports`で`Google Phone Takeout`を選択し、`タイムライン.json`を選択してインポートしてください。
:::

# インストール
docker-composeで簡単にインストールできます。

## docker-compose.ymlのダウンロード

https://github.com/Freika/dawarich/blob/master/docker/docker-compose.yml

ここから構成ファイルを落としてきます。
もしリバースプロキシ or Cloudflare Tunnelなどで外部公開する場合、ホスト名を明示的に許可しないと接続を拒否されます。
次のように変更してください。

``` docker-compose.yml
64行目、115行目あたり
      APPLICATION_HOSTS: localhost,timeline.example.com
```
ここで許可ホストを追加する際、localhost, timeline.example.comのようにカンマのあとにスペースを入れるとうまくいかないので注意してください。

ファイルを適当に配置して、サービスを上げます。

```console
$ mkdir dawarich
$ cd dawarich
$ docker compose up -d
```

サービスが立ち上がったら、WebUIにアクセスします。アドレスは[http://localhost:3000]()です。

初期ログイン用のメールアドレスとパスワードは次の通りです。
```
メールアドレス: demo@dawarich.app
パスワード: password
```
::: note alert
初期ログイン後は右上のメールアドレスが表示されている部分をクリックし、`Account`タブからメールアドレスとパスワードを必ず変更してください。
:::

# データインポート
Androidスマホの`設定 -> 位置情報 -> 位置情報サービス -> タイムライン -> タイムラインのエクスポート`から、`タイムライン.json`をエクスポートしてください。
エクスポート後はWebUIの`Imports`で`Google Phone Takeout`を選択し、`タイムライン.json`を選択してインポートしてください。
サーバーの性能と保存期間によりますが、かなり時間がかかります。

# GPSトラッカーアプリとの接続
今回は`OwnTracks`を使います。
スマホでアプリを開いたら、`環境設定` -> `接続`へ行き、モードを`HTTP`に変更します。
URLには、`http://<your-dawarich-instance>/api/v1/owntracks/points?api_key=<your-api-key>`の形式で入力します。
実際のURLは、Dawarich WebUIのAccountタブで確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532025/09380b78-2b10-8b97-4919-d4b25632e2b9.png)

これでトラッカーとの接続は完了です。

# おわり
Googleのタイムラインがブラウザから見えなくなってしまったのでかきまし
PetalinuxのビルドからSDカードを焼くまでの効率化

# はじめに
SoC開発において、FPGAに変更が加わるたびに論理合成/配置配線の結果をBootファイルなどと統合してSDカードに焼く必要が出てくることがあります。その手間を最小限にするスクリプトを書きました。

# 前提条件
- Ubuntu 22.04.2 LTS
- Vivado v2024.1 (64-bit)
- PetaLinuxツール v2024.1

あらかじめ```petalinux-create```でプロジェクトを作成、```petalinux-config```でハードウェアコンフィギュレーション(.xsa)をインポートしているものとします。

# スクリプト

以下のスクリプト(rebuild.sh)をプロジェクトディレクトリに置き実行します。
一部Superuserにならないといけないところでは、expectを使い自動化しています。
rootのパスワードは```xxxxxxxx```、userは```aaaaaaaa```としています。
SDカードのマウント場所や```/dev/sdx```は適宜確認してください。


```bash:rebuild.sh
#!/bin/bash

echo "Start rebuilding!"

petalinux-build
petalinux-package --boot --u-boot --force
cd images/linux
rm -rf ramdisk*
dd bs=64 skip=1 if=rootfs.cpio.gz.u-boot of=ramdisk.cpio.gz
gunzip ramdisk.cpio.gz
mkdir ramdisk && cd ramdisk
cpio -i -F ../ramdisk.cpio
cd ..

path=\".*#\"

expect -c "
set timeout 20
spawn su
expect \"Password:\"
send \"xxxxxxxx\r\"
expect -re ${path}
send \"mount /dev/sdb1 /media/aaaaaaaa/boot\r\"
expect -re ${path}
send \"mount /dev/sdb2 /media/aaaaaaaa/root\r\"
expect -re ${path}
send \"cp -rf ramdisk/lib/modules /media/aaaaaaaa/root/lib/\r\"
expect -re ${path}
send \"cp -rf BOOT.BIN boot.scr image.ub /media/aaaaaaaa/boot/\r\"
expect -re ${path}
send \"umount /dev/sdb1\r\"
expect -re ${path}
send \"umount /dev/sdb2\r\"
expect -re ${path}
"
echo ""

exit 0
```

# 関連
https://qiita.com/shirunari/items/66ba96ca0d75b197f44e
Agentforce Service Agentの概要

# Agentforce Service Agentとは？
Salesforceの提供する生成AIベースのチャットボットです。

# Agentforce Service Agentを試すには？
以下のTrailheadから試すための環境をプロビジョニングできます。
https://trailhead.salesforce.com/ja/content/learn/projects/quick-start-build-your-first-agent-with-agentforce/configure-an-agentforce-service-agent

# どんな仕組み？
当然のことながら、無秩序に生成AIを開放しているわけではありません。
無秩序に生成AIを開放すると、以下のような問題が起きるためと考えられます。
1. 本来の役割(企業のサービスに関する質問、注文等)を超えた要求をされる可能性がある
2. 喋ってはいけないこと(他人のデータ等)を喋ってしまう可能性がある

以下の仕組みで、生成AIに縛りをかけているようです。
1. データアクセスについては、Apexまたはアクション経由で実行させる。
2. エージェントに対してプロファイルと権限セットを適用する。つまり、あたかも1ユーザであるかのようにエージェントに権限を付与し、それ以外のことは禁じる。
3. スクリプトエンジニアリングを開発者に強制する。エージェント作成時に、必須の設定項目としてエージェントのロールや目的を記入させる欄を用意する。

# 試してみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573815/c86467c5-4336-cd7b-8d1f-fb53556b6064.png)
旅行ツアーに関する質問をしたら、回答してくれました！Thank youというお礼の言葉にも柔軟に返答してくれています。

# 悪意のあるユーザに耐えられるか？
ChatGPTは、様々なテクニックでAIを欺くことで、本来ブロックされているはずの有害コンテンツを生成できてしまうことが知られています。
https://japan.zdnet.com/article/35207115/
Agentforce Service Agentを欺いて、他人の個人情報を吐き出させることができると問題です。そうしたことが可能か、簡単に試してみました。会社(org)内のユーザの一覧を吐き出させようとしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573815/a61ff2bb-1d48-87dc-e427-068a30f186da.png)
結果、吐き出してくれませんでした。あの手この手で騙そうとしてみましたが、びくともしません。一般的に、ロールをプロンプトで与えただけでは生成AIは他の指示を与えることでロールを忘れさせることができるので、恐らくは前述の「データアクセスについては、Apexまたはアクション経由で実行させる」という仕組みが効いているのではないかと推測しています。

# どこまで柔軟か？
「データアクセスについては、Apexまたはアクション経由で実行させる」という仕組みが効いているならば、柔軟な返答はできないと推測されます。試しに、Trailheadに書かれていない文章で、ビーチに関する旅行ツアーがあるかを聞いてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573815/b94a7d29-c5e5-5dbf-e1ce-e6812495011a.png)
・・・見つけられなかったようです。(本当は Full moon beach partyがあるのに！)
AIの頭の中がログとして出力されるので、それを見ると、どうやらAIはあくまでアクション(今回はフロー)を選択し、そのInputとしてbeach tourを入れ込んでいるようです。フローは生成AIに基づかないため、単純なDB検索を行い、ヒットしなかったため、見つけられなかったようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573815/808a08f5-969f-3b71-72a2-319fb2720b8d.png)
柔軟さとセキュリティがトレードオフの関係にあり、セキュリティを重視したのではないかと私は推測しています。

# まとめ
これらの結果からAgentforce Service Agentは以下のような存在だと考えられます。
1. ユーザから送られたチャット文章を、まずは生成AIが解釈をする。
2. 生成AIは、事前に与えられたロールに従ってアクションを考える。ロール外の事項に関する質問は断る。
3. アクション(データアクセス等)を実行する

少々意外だったのは、生成AIが受け持つ範囲は1~2だけであることです。

データアクセスを伴う処理はアクションで定義されている内容に従うため、顧客の要求に柔軟に答えるためにはアクションを沢山作るか、柔軟に回答できるアクションを作る必要がありそうです。
「ナレッジを基に回答する」という程度であれば作りこみは少なくて済みそうですが、様々な申し込みに対応するには、人間のエージェントが申し込みできるようにするのと同様にアクションを作りこむ必要がある点に注意しましょう。
ブラックボックステストの手法と目的

ブラックボックステストは、ソフトウェアテストの手法の一つで、システムの内部構造やコードを考慮せずに、外部からの入力と出力のみに基づいて動作を検証する方法です。テスト対象のプログラムを「黒い箱」とみなし、その内部の仕組みを知らなくても、正しく動作しているかを確認します。

# ブラックボックステストの目的

ブラックボックステストの主な目的は以下の通りです：

**機能の確認**：

ソフトウェアが仕様書通りに動作するかを検証します。

例えば、ユーザーが入力したデータに対して期待通りの結果が返されるかを確認します。

**エラー検出**：

入力ミスや予期しないデータに対するシステムの耐性を確認します。

エラー処理が正しく行われているかを検証します。

**ユーザー視点の検証**：

実際のユーザーの使い方をシミュレーションし、ユーザー体験が適切かどうかを確認します。

# ブラックボックステストの利点

**内部知識不要**：

テスターはソースコードや内部構造を知らなくてもテストを実行できます。

ユーザー目線でのテスト：

実際の使用状況に近い形でテストを行えるため、ユーザー体験の向上に繋がります。

**幅広いカバレッジ**：

様々な入力データや条件を使ってテストを行うため、多くのケースを検証できます。

# ブラックボックステストの手法

ブラックボックステストにはさまざまな手法があります。以下に代表的な手法を挙げます：

**同値分割 (Equivalence Partitioning)**

入力データをいくつかのグループ（同値クラス）に分け、それぞれから代表的な値を選んでテストを行います。

例：入力が1–100の間である場合、1–50、51–100の2つのクラスに分けます。

**境界値分析 (Boundary Value Analysis)**

入力の境界値（最小値、最大値、その近辺）をテストします。

例：範囲が1–100なら、0, 1, 100, 101などをテスト。

**原因結果グラフ (Cause-Effect Graphing)**

入力（原因）と期待される出力（結果）との関係を図示し、それに基づいてテストケースを設計します。

**エラー推測 (Error Guessing)**

過去の経験や直感に基づいて、エラーが発生しやすい部分を予測してテストします。

例：空白文字や特定の特殊文字の入力。

# ブラックボックステストの具体例

例1: ログイン画面のテスト

ログイン画面が以下の仕様を持つとします：

ユーザー名とパスワードを入力する。

ユーザー名は1–20文字の英数字。

パスワードは8–16文字の英数字。

**テストケース例：**

正しいユーザー名とパスワードを入力し、ログインできることを確認。

ユーザー名が空白の状態でエラーメッセージが表示されることを確認。

パスワードが8文字未満の場合、エラーとなることを確認。

パスワードが16文字を超える場合、エラーとなることを確認。

特殊文字を入力してシステムが正しく対処するかを確認。

コード例 (Java):
```Java
public class LoginValidator {

    public static String validateLogin(String username, String password) {
        if (username == null || username.isEmpty() || username.length() > 20 || !username.matches("[a-zA-Z0-9]+")) {
            return "Invalid username";
        }

        if (password == null || password.length() < 8 || password.length() > 16 || !password.matches("[a-zA-Z0-9]+")) {
            return "Invalid password";
        }

        return "Login successful";
    }

    public static void main(String[] args) {
        // テストケース
        System.out.println(validateLogin("user1", "password123")); // Login successful
        System.out.println(validateLogin("", "password123"));      // Invalid username
        System.out.println(validateLogin("user1", "pass"));        // Invalid password
        System.out.println(validateLogin("user1", "password123456789")); // Invalid password
    }
}
```

注意点と課題

ブラックボックステストには以下の課題も存在します：

内部エラーの見逃し：

内部構造を無視するため、コード内のロジックエラーやパフォーマンス問題を見逃す可能性があります。

テストケースの設計が難しい：

仕様書が不十分な場合、効果的なテストケースを作成するのが困難です。

全ケースの網羅は不可能：

入力条件が多い場合、すべての組み合わせをテストするのは現実的ではありません。

**結論**

ブラックボックステストは、システムの動作をユーザー視点で検証するための重要な手法です。特に機能テストや受け入れテストの段階で有効ですが、内部構造の検証が必要な場合はホワイトボックステストと併用することが推奨されます。
Rustで線分の交差判定を実装する

解説は他記事で詳しいのがあるので割愛します。

- P1P2とP1P3の外積とP1P2とP1P4の外積の積が負
- P3P4とP3P1の外積とP3P4とP3P2の外積の積が負

を用いて判定しています。

コードは以下

```Rust
// 線分p1p2とp3p4が交わるかどうかを判定する
fn intersect(p1: (i64, i64), p2: (i64, i64), p3: (i64, i64), p4: (i64, i64)) -> bool {
    outer_product(p1, p2, p3) * outer_product(p1, p2, p4) < 0
        && outer_product(p3, p4, p1) * outer_product(p3, p4, p2) < 0
}

// p1p2とp1p3の外積
fn outer_product(p1: (i64, i64), p2: (i64, i64), p3: (i64, i64)) -> i64 {
    let a = p2.0 - p1.0;
    let b = p2.1 - p1.1;
    let c = p3.0 - p1.0;
    let d = p3.1 - p1.1;
    a * d - b * c
}


```
RustでCode Golfをやってみた

以下の問題の今のところの最短解です。
短くしていくプロセスをメモ的に残します。

https://code.golf/prime-numbers-long#rust

初期コード。
素数判定は本当は$O(\sqrt{N})$でできるが、まあ今回は短ければいいので$O(N)$
238byte

```Rust
fn main() {
    for i in 1..=10000 {
        if is_prime(i) {
            println!("{}", i);
        }
    }
}

fn is_prime(n: i32) -> bool {
    for i in 2..n {
        if n % i == 0 {
            return false;
        }
    }
    true
}
```

不要なインデントは消して提出します。
132byte

```Rust
fn main(){for i in 1..=10000 {if is_prime(i){println!("{}",i)}}}
fn is_prime(n:i32)->bool{for i in 2..n{if n%i==0{return false}}true}
```

(実際の提出時はインデント消してます。)
関数のインライン化。関数宣言の文字数がもったいない。
122byte

```Rust
fn main() {
    for i in 1..=10000 {
        let mut is_prime = true;
        for j in 2..i {
            if i % j == 0 {
                is_prime = false;
            }
        }
        if is_prime {
            println!("{}", i);
        }
    }
}
```

変数名が2文字以上は言語道断です。
101byte

```Rust
fn main() {
    for i in 1..=10000 {
        let mut p = true;
        for j in 2..i {
            if i % j == 0 {
                p = false;
            }
        }
        if p {
            println!("{}", i);
        }
    }
}
```

条件の部分、`any`を使って書けそう。
73byte
```Rust
fn main() {
    for i in 1..=10000 {
        if !(2..i).any(|j| i % j == 0) {
            println!("{}", i)
        }
    }
}
```

not anyはallですね
72byte
```Rust
fn main() {
    for i in 1..=10000 {
        if (2..i).all(|j| i % j != 0) {
            println!("{}", i)
        }
    }
}
```

改行つきでprintした方が文字数が少ない
71byte
```Rust
fn main() {
    for i in 1..=10000 {
        if (2..i).all(|j| i % j != 0) {
            print!("{}
", i)
        }
    }
}
```

実は`print{i}`って書ける
70byte
```Rust
fn main() {
    for i in 1..=10000 {
        if (2..i).all(|j| i % j != 0) {
            print!("{i}
")
        }
    }
}
```

10000までの閉区間は10001までの開区間
69byte
```Rust
fn main() {
    for i in 1..10001 {
        if (2..i).all(|j| i % j != 0) {
            print!("{i}
")
        }
    }
}
```

10000と9999は素数ではないので、範囲を狭められる
68byte
```Rust
fn main() {
    for i in 1..9999 {
        if (2..i).all(|j| i % j != 0) {
            print!("{i}
")
        }
    }
}
```

`!=0`と書くよりも`>0`と書いた方が1文字節約できる
67byte
```Rust
fn main() {
    for i in 1..9999 {
        if (2..i).all(|j| i % j != 0) {
            print!("{i}
")
        }
    }
}
```

提出コード
```Rust
fn main(){for i in 2..9999{if(2..i).all(|j|i%j>0){print!("{i}
")}}}
```
共通テスト対策！ 相関係数をグラフから見積って当てるゲーム

# 相関係数について
皆さんは相関係数をご存じでしょうか？
相関係数とは2つの変数の間に存在する関係の強弱を数値で表す統計量で、-1から+1までの値をとります。

定義や計算方法を知っている方は多いでしょうが、相関係数が0.8とか0.6とか言ったときに
実際にはグラフがどんな見た目になっているかは気にしたことがない方も多いのではないでしょうか

実務ではグラフを眺めて"相関係数が0.6と出てきたけどこれ本当にあっているのかな？"とかチェックすることもありますから、見た目を押さえておくことも重要なのかもしれません（本当か？）
この受験生の盲点を突いた奇問が実際に今日共通テストで出題されたこともあります
![14-21_1-768x432.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638607/da8a08da-28ac-6fc0-b83a-15eec86fc194.jpeg)
（共通テスト 2022より引用）

今や大卒者もこぞってエンジニアを目指す時代・志望大学に入れなければキャリアの出鼻をくじかれたような気分にエンジニア志望受験生はなってしまうかもしれません
相関係数を目算できないエンジニアは生き残れない時代がやってきたといっても過言ではないでしょう

# さっそく作った
そこでみんなの相関係数眼を鍛えるべく、相関係数をグラフから見積って当てるゲームを作ることにしました。
受験生が学校や塾の合間にも手早く遊べるようにhtmlとjavascriptで書いてブラウザで動くようにしました

JSでグラフ描画といえばChart.jsということでインポート
```
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.0/chart.min.js"
integrity="sha512VMsZqo0ar06BMtg0tPsdgRADvl0kDHpTbugCBBrL55KmucH6hP9zWdLIWY//OTfMnzz6xWQRxQqsUFefwHuHyg==" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@next/dist/chartjs-adapter-date-fns.bundle.min.js">
```

ランダムに生成したを描画
```
function draw(){
    // sum関数を使うので定義
    const sum = function(a){return a.reduce((a, b) => a + b, 0);}

    // 描画対象
    var ctx = document.getElementById('chart');
    ctx.width = 600;
    ctx.height = 400;

    // 10点を生成
    const len = 10;
    const xs = [...Array(len).keys()].map((d) =>{ return Math.random() * 100;});
    const ys = [...Array(len).keys()].map((d) =>{ return Math.random() * 100;});
    const xxs = [...Array(len).keys()].map((d) =>{ return xs[d] * xs[d]});
    const yys = [...Array(len).keys()].map((d) =>{ return ys[d] * ys[d]});
    const xys = [...Array(len).keys()].map((d) =>{ return xs[d] * ys[d]});
    const data = [...Array(len).keys()].map((d) =>{ return {x: xs[d], y: ys[d]}});

    // 相関係数を計算
    const ave_x = sum(xs) / len;
    const ave_y = sum(ys) / len;
    const ave_xx = sum(xxs) / len;
    const ave_yy = sum(yys) / len;
    const ave_xy = sum(xys) / len;
    const s_xy = ave_xy - ave_x * ave_y;
    const s_x = ave_xx - ave_x * ave_x;
    const s_y = ave_yy - ave_y * ave_y;
    rho = s_xy / Math.sqrt(s_x * s_y);
    rhoq = Math.round(rho * 5) / 5;
    rhoq = Math.min(0.6, rhoq);
    rhoq = Math.max(-0.6, rhoq);

    // チャートに描画
    myChart = new Chart(ctx, {
      type: 'bubble',
      data: {
        datasets: [{
          label: 'Dataset#1',
          data: data,
          backgroundColor: '#f88',
        }],
      },
      options: {
        scales: {
          y: { min: 0, max: 100 },
          x: { min: 0, max: 100},
        },
      },
    });
  };
```

htmlで画面を整えたらこのようなものの完成！
![corr1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638607/16ffe8dd-72cb-ef7d-d10d-e07166fe503c.png)


# やってみた
![corr2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638607/91001692-3642-d44c-087c-e41b61cb9741.png)
意外と難しく自分でもなかなか正解しない

![corr3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638607/b9958247-66c7-7e2d-77bd-56c73acb4fea.png)
やった！あたり

# みんなもチャレンジ！
ここから無料で遊べるようにしたので試験を控える受験生の皆さんはぜひ遊んでみてね
https://wonderhorn.net/game/correlation.html
乱数の使い方

### 乱数を生成してみる!

乱数を生成するにはRandomクラスを使うのです
まず、Randomクラスのインスタンスを作成します
```title.cs
Random rnd = new Random();//インスタンスの作成
rnd.Next(1, 10);//1~9までの乱数を生成
```
インスタンスってなんやねんって思いますよね
私も書いてて意味わからなかったので調べました

### インスタンスって？？
クラス：どんなものかを表した設計図、概念のようなもの
インスタンス：設計図（クラス）をもとに作った実体
コンストラクタ：インスタンスができたタイミングで実行されるメソッド

### インスタンスを作成
Randomクラスは色んな種類の乱数を生成するときに使用される
クラスを使うには、そのクラスのインスタンスを使って乱数を生成する!!

そして最初に戻ってきます
```title.cs
Random rnd = new Random();//インスタンスの作成
```
new演算子：クラス（設計図）からインスタンス（実体）を作るときに使う演算子

最初の`Random`はクラスのこと
`new`をつけることで、インスタンスを生成しています
変数`rnd`にはインスタンスが格納されているイメージかな？？

### Next()で乱数の範囲を指定する
`Next()`のカッコに引数を指定し、範囲を決めることができる
```title.cs
int number = rnd.Next(1,10);//乱数は1~9の範囲で出力
Console.WriteLine(number);
```
AWS DVA対策メモ(AWS Step Functuons)

# AWS Step Functions とは？

AWS Step Functionsは、分散アプリケーションやマイクロサービスを**ワークフロー形式で調整**できるサーバーレスサービスです。複雑なビジネスロジックやプロセスを**可視化**し、簡単に構築・運用できます。

---

## 特徴

### 1. **可視化されたワークフロー**
- 状態遷移（State Machine）をフローチャートで表現。
- ワークフロー全体の構造や進行状況をリアルタイムで確認可能。

### 2. **フルマネージド型**
- インフラ管理不要。
- 高可用性とスケーラビリティを備え、複雑なプロセスも信頼性を確保。

### 3. **AWSサービスとの統合**
- **AWS Lambda**、**DynamoDB**、**S3**、**SNS**、**SQS** など、幅広いAWSサービスとシームレスに連携。

### 4. **エラー管理とリトライ**
- 自動リトライ、タイムアウト、エラーハンドリングを設定可能。
- エラー発生時の通知や代替処理が簡単に実装できる。

### 5. **2つのワークフロータイプ**
- **標準ワークフロー**: 長時間実行（最大1年）、高耐障害性。
- **エクスプレスワークフロー**: 高スループット、短時間処理（最大5分）。

---

## ステートマシンとは？

### 1. **概要**
ステートマシンは、Step Functionsで定義される**ワークフロー全体**を指します。
- ワークフローを構成する個々のステップ（状態）を**ステート**として定義。
- ステート間の遷移や条件分岐を管理。
- JSONまたはYAML形式で構築。

---

### 2. **ステートのタイプ**

| ステートタイプ      | 説明                                                                                   | ユースケース例                              |
|--------------------|---------------------------------------------------------------------------------------|-------------------------------------------|
| **Task**          | Lambdaや他のAWSサービスを呼び出す。                                                       | データ処理、ファイル変換。                   |
| **Choice**        | 条件分岐を実行し、異なるステートに遷移。                                                   | データ内容による分岐処理。                   |
| **Parallel**      | 複数のステートを並列で実行。                                                             | 複数のファイルを同時に処理。                 |
| **Map**           | 配列データをループ処理し、各要素に対してステートを実行。                                    | 配列内の各オブジェクトに対するバッチ処理。     |
| **Wait**          | 指定した時間だけ待機。                                                                   | 時間経過後の処理や遅延実行。                 |
| **Fail**          | 実行を失敗として終了し、エラー情報を返す。                                                 | エラー発生時のワークフロー終了。             |
| **Succeed**       | 実行を成功として終了。                                                                   | 成功時のワークフロー終了。                   |
| **Pass**          | データをそのまま次のステートに渡す。                                                       | 単純なデータ引き渡し。                       |

---

### 3. **実装例: Lambda関数の呼び出し**
```json
{
  "Comment": "Lambdaを呼び出すステートマシン",
  "StartAt": "LambdaFunction",
  "States": {
    "LambdaFunction": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:region:account-id:function:example-function",
      "Next": "SucceedState"
    },
    "SucceedState": {
      "Type": "Succeed"
    }
  }
}
【Python】フィボナッチ数

## はじめに
Pythonでフィボナッチ数列を出力する問題を解いてみた。
再帰関数を用いて解くパターンが多いらしいが、まだそこまで学習が追い付いてなくて理解が難しかったので、他の方法で実装してみた。


## フィボナッチ数列とは
定義や概要などはWikipediaを参照。数学的に有名な数列の1つ。

https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3%83%83%E3%83%81%E6%95%B0

プログラム的な活用法としては、主に初心者の練習問題として扱われる他、各言語の演算速度を測定するために用いられることもあるらしい。


## 問題
フィボナッチ数列をn番目まで表示してください。


## 実装の過程
まずは下準備として、最初の2数をあらかじめリストに代入しておく。
``` python
list_1 = [1, 1]
```
nをユーザー入力させるための下準備を行う。
``` python
n = int(input())
```
n番目までの数をfor文で出力。
``` python
for i in range(n):
```
最初の2数に関しては、既に準備したリストより出力すれば良いだけなので、
``` python
    if (i == 0) or (i == 1):
        print(list_1[i])
```
3番目以降の数は、リストの末尾の2数を合計すれば求められる。
計算結果を変数`sum`に代入。
``` python
    else:
        num = list_1[-1] + list_1[-2] 
```
ループ前に`sum`をリストに追加するのを忘れない。
``` python
        list_1.append(num)
        print(num)
```

## 出力結果
ここでは例として`n = 15`の場合を記す。
```
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
```

## まとめ
最後に上記のコードをまとめたものを掲載しておく。
``` python
list_1 = [1, 1]   # リストの準備

n = int(input())   # ユーザー入力の受付

for i in range(n):

    # 最初の2数の出力
    if (i == 0) or (i == 1):
        print(list_1[i])

    # 3番目以降の数の演算・出力
    else:
        num = list_1[-1] + list_1[-2]   # リスト末尾の2数を合計すれば求められる
        list_1.append(num)   # 計算結果をリスト末尾に追加する
        print(num)
```
GAS ウェブアプリとしてデプロイしたときのdoPost(e)のeに入るもの

## 概要

GASのコードをPOSTのウェブアプリとしてデプロイしたときに`doPost(e)`の関数を定義するはずである。このeに入ってくる内容が記載されている先のリンクを貼っておく。

## 記載場所

https://developers.google.com/apps-script/guides/web?hl=ja#request_parameters
Go言語(プログラミング)入門メモ⑨

## new関数について
スライスやマップを作成する際にmake関数を使った。これと同じようなものとしてnew関数がある。new関数はメモリを確保するための関数で、ポインタなどを作成する際に必要となる。

## newを使ってポインタのアドレスを確保する
入門メモ⑧までは、まずint型の変数nを宣言し変数nのアドレスを「var p *int = &n」
というように変数pに代入して、ポインタを初期化していた。
new関数を使うと、値を何も代入しない状態で、メモリにポインタが入る領域を確保できる。次のように「var p *int = new(int)」と書いて、new関数でポインタの変更を作成して表示すると変数pのアドレスは表示される
~~~
var p *int = new(int)
fmt.Println(p) 

//以下のように出力される
014000112018
~~~
次のように、new関数を使わずにポインタの変数を宣言して表示すると<nil>と表示される。
~~~
var p *int = new(int)
fmt.Println(p) 

var p2 *int 
fmt.Println(p2) 

//以下のように出力される
014000112018
<nil>
~~~
new関数を使ってポインタを宣言すると、メモリの領域を確保する。
変数を表示するとアドレスが表示される。(このアドレスには値は入っていない)
一方で、new関数を使わない場合、まだメモリを確保していないので、ポインタの初期値である<nil>という値が表示される。

new関数で作成した変数pの初期値を確認するとint型の初期値0が表示されることを確認できる。
~~~
var p *int = new(int)
fmt.Println(*p)

//以下のように出力される
0
~~~
ここで、*p++として変数pの実体に++で足し算をしてくと0,1と計算が行われていることが分かる。
~~~
var p *int = new(int)
fmt.Println(*p)
*p++
fmt.Println(*p)

//以下のように出力される
0
1
~~~
対して、new関数を使用しないで宣言したポインタに++を実行してもエラーになってしまう。これはnew関数を使わない場合はメモリの領域が確保されておらず、ポインタの中身にアクセスして足し算をしようとしてもエラーが発生してしまうことになる。

~~~
var p2 *int 
fmt.Println(p2)

*p2++
fmt.Println(p2)
//以下のように出力される
<nil>
panic:runtime error:,,,(以下略)
~~~

## new関数とmake関数の違い
new関数と似たものとしてmake関数(mapとスライスを作成する際に出てきたもの)がある。
スライスやマップはmake関数で、ポインタはnew関数で作成する。それぞれのデータ型を確認してみると、以下のようになる。
~~~
s := make([]int, 0)
fmt.Println("%T\n", s)

m := make(map[string]int)
fmt.Println("%T\n", m)

var p *int = new(int)
fmt.Println("%T\n", p)

//以下のように出力される
[]int
map[string]int
*int
~~~
new関数とmake関数の違いは、肩を確認したときにポインタを返す場合はnew関数でそれ以外の場合はmake関数を使うということになる。

## 学習に使用した教材
・『入門】Golang基礎入門 + 各種ライブラリ + 簡単なTodoWebアプリケーション開発(Go言語)』M.A EduTech
https://www.udemy.com/course/golang-webgosql/?utm_medium=udemyads&utm_source=bene-msa&utm_campaign=responsive&utm_content=top-1&utm_term=general&msclkid=81e2f24a32cc185d275d953d60760226&couponCode=NEWYEARCAREERJP

・『シリコンバレー一流プログラマーが教える Goプロフェッショナル大全』酒井 潤 (著)
https://www.amazon.co.jp/%E3%82%B7%E3%83%AA%E3%82%B3%E3%83%B3%E3%83%90%E3%83%AC%E3%83%BC%E4%B8%80%E6%B5%81%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC%E3%81%8C%E6%95%99%E3%81%88%E3%82%8B-Go%E3%83%97%E3%83%AD%E3%83%95%E3%82%A7%E3%83%83%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB%E5%A4%A7%E5%85%A8-%E9%85%92%E4%BA%95-%E6%BD%A4/dp/4046070897
#0016（2024/01/16）locals()を使って、関数内の変数を辞書型としてグローバルに格納する

# モチベーション
- 関数内で使用した変数を辞書型としてグローバルに格納したいことがあった

# 関数内で使用した変数を辞書型としてグローバルに格納する

- `locals()` : 現在のスコープ内で定義されているすべてのローカル変数を辞書形式で返す関数

``` python
global_dict = {}

def function():
    now = datetime.datetime.now()
    global global_dict
    global_dict[datetime.datetime.now()] = locals()

function()
function()
function()
function()

for key, val in global_dict.items():
    print(key)
    print(val)
    print()
```


``` shell
# 出力結果
2025-01-16 20:49:07.752355
{'now': datetime.datetime(2025, 1, 16, 20, 49, 7, 752351)}

2025-01-16 20:49:07.752387
{'now': datetime.datetime(2025, 1, 16, 20, 49, 7, 752385)}

2025-01-16 20:49:07.752415
{'now': datetime.datetime(2025, 1, 16, 20, 49, 7, 752414)}

2025-01-16 20:49:07.752443
{'now': datetime.datetime(2025, 1, 16, 20, 49, 7, 752441)}
```
「SQLアンチパターン」の気づき（クエリ2）

## はじめに

こんにちは。小川です。
以前から気になっていた「SQLアンチパターン」という本を読みました。
とても良い本で今まで気づかずにやっていたことがSQLアンチパターンなんだと知ることができました。
勉強になったので、学んだことを言語化して量が多いのでいくつかの記事に分けて紹介していこうと思います。
今回は第Ⅲ部のクエリのアンチパターンについて記載します。
この記事は[「SQLアンチパターン」の気づき（クエリ2）](https://qiita.com/pesysyon/items/84584fdc422254e0260f)の続きになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/edfcea05-fe0b-f2b8-c4c9-0881241eae1e.png)

## 15章.ランダムセレクション

#### アンチパターン：データをランダムにソートする
SQLでランダムな行を取得するための最も一般的な方法は、ランダムにソートを行い、最初の行を取得するというものです。
```sql
SELECT * FROM Bugs ORDER BY RAND() LIMIT 1;
```

#### デメリット
- ランダムにしたデータからデータを取得する方法はデータベースのパフォーマンスが落ちる
  - インデックスからメリットを得られない(実行するたびに結果が変わるため)
  - すべての結果を一時的なテーブルとして保存し、物理的に行を入れ替える処理を行う（テーブルスキャン）ため、データセットのサイズが大きくなるにつれてパフォーマンスも落ちる

#### 解決策：特定の順番に依存しない
- 1と最大値の間のランダムなキー値を選択する
  - テーブル全体のソートを回避するための方法は、1から主キーの最大値までの間の値をランダムに選択すること
  - 主キーが1から始まり、連続している必要がある
```sql
SELECT b1.*
FROM Bugs AS b1
INNER JOIN (
    SELECT CEIL(RAND() * (SELECT MAX(bug_id) FROM Bugs)) AS rand_id
) AS b2 ON b1.bug_id = b2.rand_id
```
- 欠番の穴の後にあるキー値を選択する
  - １と最大キー値の間に欠番があり、かつ乱数によって欠番のキー値が算出される場合に、このクエリは欠番の穴の後にあるキー値を使う
```sql
SELECT b1.*
FROM Bugs AS b1
INNER JOIN
    SELECT CEIL(RAND() * (SELECT MAX(bug_id) FROM Bugs)) AS bug_id
) AS b2 ON b1.bug_id >= b2.bug_id
ORDER BY b1.bug_id
LIMIT 1
```
- すべてのキー値のリストを受けとり、ランダムに１つを選択する
  - 取得したリストのサイズが大きい場合、メモリのリソースを超えてしまいエラーになる
- オフセットを用いてランダムに行を選択する
  - データセットの行数をカウントし、0と行数までの間の乱数を返す
  - キー値が連続していることが前提とできず、各行が平等に選択される必要がある場合に使用できる
- べンダー依存の解決策
  - ほとんどのデータベース製品には、この章の目的を実現するための独自の解決策が実装されている 

## 16章.プアマンズ・サーチエンジン（貧者のサーチエンジン）

#### アンチパターン：パターンマッチ述語を使用する
SQLには文字列比較のためのパターンマッチ述語があり、キーワード検索をする際にLIKE述語がよく使われます。
LIKE述語は、０個以上の文字と一致するワイルドカード（％）を扱うことができキーワードの、キーワードの前後にこのワイルドカードを使用すると、その語が含まれるすべての文字列がマッチします。
```sql
SELECT * FROM Bugs WHERE description LIKE '%crash%';
```

#### デメリット
パターン述語を使うことによる問題点として以下が挙げられます。
- パフォーマンスの低下
  - パターンマッチ述語は従来型のインデックスのメリットを得られないため、テーブル全ての行をスキャンしなければならない
  - LIKEや正規表現を用いた単純なパターンマッチでは、意図しないマッチが生じてしまう
  - 以下のクエリは、単語「one」を含むテキストとマッチしますが、「money」、「prone」、「lonely」などもマッチしてしまいます
```sql
SELECT * FROM Bugs WHERE description LIKE '%one%';
```

#### 解決策：適切なツールを使用する
最善の方法は、SQLの代わりに全文検索エンジンを使うことです。次善の策は、繰り返しのコストを減らすために検索結果を保存することです。


## まとめ
今回は第Ⅲ部のクエリのアンチパターンについて一部まとめてみました。
この記事はこの本を読んで、私がこういう理解をしましたということを言語化してみました。
とても勉強になる本なので皆様もぜひ読んでみてください。

以上、小川でした。
各種システム及びコマンドのプロキシ設定ガイド

# はじめに
既に3週間は何かの病気に掛かり続けている [@\_\_\_nix___](https://twitter.com/___nix___)  です。


# 背景
制約のある環境では経路も限定されていることがあります。
或いは特定のIPからの接続のみ許可されているケースもあります。

そんな時はプロキシを経由して外部にアクセスします。


# 概要
プロキシ経由のアクセスですが、OSの設定をしたとしてもシステムやコマンドが独自に経路を決めてしまうので、「あれ？設定したのにプロキシ経由にならないな」ということが発生します。

今回、OSやシステム、或いはコマンドによるプロキシ設定をまとめてみました。


# 設定方法

## 1. Linux システム全般

### 環境変数による設定

```bash
export HTTP_PROXY=http://xxx.xxx.xxx.xxx:80
export HTTPS_PROXY=http://xxx.xxx.xxx.xxx:80
export http_proxy=http://xxx.xxx.xxx.xxx:80
export https_proxy=http://xxx.xxx.xxx.xxx:80
export no_proxy=localhost,127.0.0.1

```

### システム全体の設定 (/etc/environment)

```bash
HTTP_PROXY=http://xxx.xxx.xxx.xxx:80
HTTPS_PROXY=http://xxx.xxx.xxx.xxx:80
http_proxy=http://xxx.xxx.xxx.xxx:80
https_proxy=http://xxx.xxx.xxx.xxx:80
no_proxy=localhost,127.0.0.1

```

## 2. パッケージマネージャー

### yum (/etc/yum.conf)

```bash
proxy=http://xxx.xxx.xxx.xxx:80

```

### apt (/etc/apt/apt.conf)

```bash
Acquire::http::Proxy "<http://xxx.xxx.xxx.xxx:80>";
Acquire::https::Proxy "<http://xxx.xxx.xxx.xxx:80>";

```

## 3. 開発ツール

### Docker

#### Dockerfile内

```
ENV http_proxy <http://xxx.xxx.xxx.xxx:80>
ENV https_proxy <http://xxx.xxx.xxx.xxx:80>

```

#### Docker デーモン設定 (/etc/systemd/system/docker.service.d/http-proxy.conf)

```
[Service]
Environment="HTTP_PROXY=http://xxx.xxx.xxx.xxx:80"
Environment="HTTPS_PROXY=http://xxx.xxx.xxx.xxx:80"

```

### Git

```bash
git config --global http.proxy <http://xxx.xxx.xxx.xxx:80>
git config --global https.proxy <http://xxx.xxx.xxx.xxx:80>

```

### npm

```bash
npm config set proxy <http://xxx.xxx.xxx.xxx:80>
npm config set https-proxy <http://xxx.xxx.xxx.xxx:80>

```

### composer

```bash
composer config -g github-oauth.github.com <token>
composer config -g http-basic.repo.packagist.com token <token>

```

## 4. ユーティリティツール

### wget (/etc/wgetrc または ~/.wgetrc)

```bash
http_proxy = <http://xxx.xxx.xxx.xxx:80>
https_proxy = <http://xxx.xxx.xxx.xxx:80>

```

### curl (~/.curlrc)

```bash
proxy-user = "username:password"
proxy = "<http://proxy.xxx.co.jp:80>"

```

### pecl/pear

```bash
pear config-set http_proxy <http://xxx.xxx.xxx.xxx:80>

```

## 5. プログラミング言語特有の設定

### Python (pip)

```bash
pip install --proxy <http://xxx.xxx.xxx.xxx:80> package_name
# または ~/.pip/pip.conf
[global]
proxy = <http://xxx.xxx.xxx.xxx:80>

```

### Maven (settings.xml)

```xml
<proxies>
  <proxy>
    <id>example-proxy</id>
    <active>true</active>
    <protocol>http</protocol>
    <host>proxy.example.com</host>
    <port>80</port>
  </proxy>
</proxies>

```

# 終わりに
以上ですが、少しは皆様の役に立てたでしょうか。
逆に設定箇所がまとまっていないのでこれらの設定に中々気が付けないということもあるかもしれませんね。


# 一言
恐らくですが、コロナとインフルとマイコプラズマと副鼻腔炎を併発してます。
皆様もお気を付けて。
Homebrew チートシート

# Homebrew

**macOS向け**のパッケージ管理システム。ソフトウェアのインストール、アップデート、アンインストールを行うことができる。

Homebrew か管理するパッケージには [Formula](#formula) と [Cask](#homebrew-cask) がある。 

## Formula

**CLI**（Command Line Interface）やライブラリのようなソフトウェア（`git`、`wget`、`node`、`python` など）。

[`$ brew install`](#-brew-install) にてインストールすることができる。

```console:Formula
$ brew install git
```

[`$ brew upgrade`](#-brew-update--brew-upgrade) にてアップデートすることができる。

```console:Formula
$ brew upgrade
```

## Homebrew Cask

Homebrew の拡張機能で、**GUI**（Graphical User Interface）アプリケーション（`google-chrome`、`visual-studio-code`、`slack` などのデスクトップアプリ）をインストール、管理する際に使用される。

[`$ brew install --cask`](#-brew-install) にてインストールすることができる。

```console:Cask
$ brew install --cask googe-chorome
```

[`$ brew upgrade --cask`](#-brew-update--brew-upgrade) にてアップデートすることができる。

```console:Cask
$ brew upgrade --cask
```

# `$ brew install`

パッケージをインストールする。

```console:macOS
$ brew install パッケージ名
```

```console:Linux 
$ sudo apt-get install package_name  # Debian系（Ubuntuなど）
$ sudo yum install package_name      # Red Hat系（CentOSなど）
$ sudo dnf install package_name      # Fedora
```


# `$ brew search`

パッケージを検索する。

```console:$ brew search
$ brew search 検索キーワード
```

# `$ brew uninstall`

パッケージをアンインストールする。

```console:$ brew uninstall
$ brew uninstall パッケージ名
```

# `$ brew list`

インストール済みのパッケージ一覧を表示する。

```console:$ brew list
$ brew list
```

# `$ brew update` / `brew upgrade`

Homebrew自体のアップデート、インストール済みのパッケージをアップデートする。

`$ brew update` は以下の2つをまとめて行う。

- Homebrew 自体のアップデート
- パッケージ取得先リポジトリを更新（fetch）

**インストール済みのパッケージはアップデートされない**。

```console:$ brew update
$ brew update
```

リポジトリを更新したら、`$ brew upgrade` によってインストール済みのパッケージがアップデートされる。

```console:$ brew upgrade
$ brew upgrade
```

[Homebrew Cask](#homebrew-cask) をアップデートする場合は、`--cask` オプションが必要。

```console:$ brew upgrade --cask
$ brew upgrade --cask
```

# `$ brew cleanup`

アップデートによって不要になったファイルを削除する。

```console:$ brew cleanup
$ brew cleanup
```

# `$ brew services`

インストールしたサービスを macOS のサービスとして起動する。

```console:$ brew services
$ brew services start mysql
```
Voisona talk等で出力した音声ファイルのタイトルをセリフにするツールをRustで書いた【初投稿】

voisona Talk等で出力された音声ファイルの名前を、同名のセリフを含むテキストファイルを参照して変換するツールをRustで書いてみたのでそれの紹介です。ほとんどREADMEのコピペかも。

ソースコードは今見ても綺麗とは言えないですが動作はちゃんとしてます。

https://github.com/Uliboooo/track2line

## 追記: 2025/03/07

GUI版を作ってみました

https://github.com/Uliboooo/track2line_gui

まだエラーハンドリングもしてないですが、一応動きます。

## Lates Release

https://github.com/Uliboooo/track2line/releases/latest

## このツールの概要と必要性

track2lineは、voisona talkなどで書き出した音声ファイルが`Talk1_1.wav`のようにトラック番号がファイル名になっており、内容が分かりにくかったため、ファイル名をその音声のセリフにしたいと考えたため制作しました。

これにはセリフが含まれる音声ファイルと同名のテキストファイルが必要です。それを自動で参照してリネームしていきます。

```bash
vt_test
├── Talk1_1.txt
└── Talk1_1.wav

$cat Talk1_1.txt
これはテストです
```

👆のようなファイルがあった際にtrack2lineを実行すると👇のようになります。

```bash
# コマンドか何かで実行
* 1.mp3                ---> one.mp3
ok?(y/n)>y
success.

├──renamed
│  ├── one.wav # 1.txtの中身を参照してone.wavに
├── 1.txt      # テキストファイル
├── bad.txt    # エラー判定用
```

ちなみに、セリフをファイルを出力するには**テキストファイルを含む**的な項目にチェックを入れると同じディレクトリにセリフを含んだテキストファイルを書き出してくれます。

![Screenshot 2025-01-16 at 20.12.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3373935/001d1bd0-6a9e-ff4d-c48e-2af28b4fe5c5.png)

## インストール

実行ファイルを置く場所をパスに通すとどこからでも使えます。

一例としてmac + zshで

```bash
echo export PATH=$PATH:ユーザディレクトリに適当なフォルダ(my_toolsなど)のフルパス >> ~/.zshrc
source ~/.zshrc
```

もしくは、実行ファイルのパスをエイリアスに登録すると、フルパスで実行ファイルを指定しなくとも使用できるようになります。(Mac)

1. 適当なフォルダに実行ファイルを置く
1. その実行ファイルのパスをaliasに設定

```bash
echo "alias track2line='track2lineのフルパス'" >> ~/.zshrc;
source ~/.zshrc;
```

## 使い方

READMEを結構ちゃんと書いたのでほとんどそれのコピペになります

## 使い方

実行方法は

- 引数にパスを指定 👉 [引数にパスを指定](#引数にパスを指定)
- 実行後にパスを指定
  - 引数ではなく実行後にパスを入力 👉 [引数ではなく実行後にパスを入力](#引数ではなく実行後にパスを入力)
  - 実行ファイルのディレクトリを自動取得 👉 [実行ファイルのディレクトリを自動取得](#実行ファイルのディレクトリを自動取得)

の3種類.

以下コードの実行に用いたテスト用のディレクトリ構造

```bash
> tree tests
tests
├── 1.txt   # テキストファイル
├── 1.wav   # 音声ファイル
├── bad.txt # エラー判定用

> cat 1.txt            
one         # テキストファイルの内容
```

### 引数にパスを指定

```bash
> ./track2line ~/Desktop/tests
* 1.wav                ---> one.wav
ok?(y/n)>y
success.
```

#### 引数に指定する場合には対応する拡張子を変更できます

*この例ではそれぞれのファイルの拡張子をmp3とrtfに変更しています.

```bash
> ./track2line -a mp3 -t rtf ~/Desktop/tests
* 1.mp3                ---> one.mp3
ok?(y/n)>y
success.
```

### 引数ではなく実行後にパスを入力

実行ファイルをダブルクリックして入力を求めらた際にフォルダのパスを入力.

```bash
> ~/Develop/track2line/target/release/track2line ; exit;
input Rust's Project folder path.
if you use current directory, just leave it blank.
>>~/Desktop/tests          # 👈パスを入力.
* 1.wav                ---> one.wav
ok?(y/n)>y
success.
```

### 実行ファイルのディレクトリを自動取得

```bash
> ~/Desktop/tests/track2line ; exit; # 👈実行ファイルのパスを指定して実行してます.
input Rust's Project folder path.
if you use current directory, just leave it blank.
>>                                   # 👈パスを入力しなければ実行ファイルのパスが自動で入力されます.
* 1.wav                ---> one.wav
ok?(y/n)>y
success.
```

## 免責事項

このソフトウェアを使用したことによって生じたすべての障害・損害・不具合等に関しては、私と私の関係者および私の所属するいかなる団体・組織とも、一切の責任を負いません。各自の責任においてご使用ください。
個人的な備忘録：半角スペースを一目で確認できるサクラエディターの便利機能を紹介してみた

## はじめに
普段はVS Codeを使用する機会が多いのですが、大事な作業や慎重に進める必要がある場合には、サクラエディターを使うこともあります。

:::note
**今回は、私がなぜサクラエディターを使うのかについて、この記事で少しだけご紹介したいと思います。**
:::

***この内容は、個人的な備忘録としてまとめたものですが、どなたかの技術的な参考になれば幸いです。***

## 書こうと思ったきっかけ
サクラエディターには、半角ブランクやスペースがある場合に、それを視覚的に分かりやすく色付けする便利な機能があります。

:::note warn
**例えば、データベースに重要なデータを挿入する際、意図しない半角スペースが含まれていないか確認する場合、この機能を必ず活用しています。**
:::

***この便利な機能をもっと多くの方に知っていただきたいと思い、この記事でご紹介することにしました。***

## 不要なスペースが入ることの恐ろしさ
そもそも、データに本来予期しない不要なスペースが入ってしまうことが、どれほど重大な問題を引き起こすかについてお伝えします。

例えば、メールアドレスをデータベースに登録する際、末尾に半角スペースが入ってしまった場合、それだけで処理が停止することがあります。

:::note alert
**処理が止まるだけであれば、半角スペースを修正することで改善できますが、最悪の場合、お客様にメールが届かないなど、業務に影響を及ぼす可能性もあります。**
:::

***このような事態を防ぐためにも、半角スペース1つに対しても慎重かつ正確に作業することが非常に重要です。***

## アナログだけど、不要なスペースの確認はサクラエディターで
正直なところ、VS Codeの機能や他のエディターを使って不要なスペースを回避する方法もありますが、私はアナログなサクラエディターを選んでいます。

![Screenshot 2025-01-16 at 19.31.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/0699db3d-db55-a144-65a9-7e03c26b43da.png)
引用画像：https://sakura-editor.github.io/images/ogp.png

特に深い理由があるわけではありませんが、***仕事の関係でVS Codeを使う機会が少なく、サクラエディターを使うことが多かったため、その習慣が定着しています（笑）。***

## 設定方法について
詳細な設定方法は、以下のサイトで画像付きで詳しく紹介されていますので、ぜひ参考にしてみてください。

https://qiita.com/a999/items/3022b9a2289282c0f539

## 実際に不要なスペースを入れてみた
では、実際にデータの末尾に不要なスペースを入れるとどのように表示されるのかを確認してみます。

ここでは、適当なメールアドレスの末尾に半角スペースを入れてみました。

![Screenshot 2025-01-16 at 19.26.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/4cce4f46-a70d-2db7-5a04-da394f56fffc.png)

***このように、赤文字でブランクがあることが視覚的に表示されるため、不要なデータが登録されるのを事前に防ぐことができます。***

## まとめ
最後までお読みいただき、ありがとうございました。

:::note info
**今回は、サクラエディターの基本的な機能の一部についてご紹介しましたが、どなたかの参考になれば幸いです。**
:::

特に半角ブランクに関する機能を取り上げましたが、サクラエディターにはこれ以外にも多くの便利な機能が搭載されています。

***ぜひ、一度触ってみて、その使いやすさを実感してみてください。***
int (32bit)配列 を ポインターとメモリー操作を使って byte に分割(戻しも)


x M5NanoC6での予定は、未定

目的
int(32ビット)2個の配列を
符号なし8ビットの配列の電文(パケット(フレーム))に
変換する


いろいろ
メモリー操作での変換は、オーバーヘッドが多すぎて
あまり、好きでは、ないが、項目が増えた場合は、しょうがないので
他の人が多くやる様にポインターの強制キャストで変換
ビットシフト操作は、いろいろ指摘も受けたし
もう少し、工夫が必要!!!
c言語の場合は、9割がた、メモリー操作なんだけど、いろいろ、わすれた


オンラインコンパイラ paiza


```c++


#include <iostream>
using namespace std;
int main(void){
    // Your code here!
    
    printf("START\n");
    
    //送信バッファー int(32bit)配列
    unsigned char ac[256+1];
    
    unsigned char *c;
    
    int s[2];
    
    s[0] = -2;    //センサーの値
    s[1] = -3;    //センサーの値

    printf("[%d],[%d]\n",s[0],s[1]);

    c = (unsigned char *)(&s[0]);
    ac[0+0]=c[0+0];
    ac[0+1]=c[0+1];
    ac[0+2]=c[0+2];
    ac[0+3]=c[0+3];
   
    ac[4+0]=c[4+0];
    ac[4+1]=c[4+1];
    ac[4+2]=c[4+2];
    ac[4+3]=c[4+3];
 
    
    
    printf("[%x][%x][%x][%x]\n",ac[0],ac[1],ac[2],ac[3]);
    printf("[%x][%x][%x][%x]\n",ac[4],ac[5],ac[6],ac[7]);

    
    int *p;
    p = (int *)(&ac[0]);
    s[0] = *p; //メモリコピー
    
    p = (int *)(&ac[4]);
    s[1] = *p; //メモリコピー

    printf("\n");
    printf("[%d],[%d]\n",s[0],s[1]);
    
}


```


```

START
[-2],[-3]
[fe][ff][ff][ff]
[fd][ff][ff][ff]

[-2],[-3]


```


・


・


いろいろ工夫
----

memcpyを使用する


```c++


#include <iostream>
#include <string.h>
using namespace std;
int main(void){
    // Your code here!
    
    printf("START\n");
    
    //送信バッファー int(32bit)配列
    unsigned char ac[256+1];
    
    unsigned char *c;
    
    int s[2];
    
    s[0] = -2;    //センサーの値
    s[1] = -3;    //センサーの値

    printf("[%d],[%d]\n",s[0],s[1]);

    c = (unsigned char *)(&s[0]);
    
    memcpy(ac, c, (sizeof s)); 
    
    printf("[%x][%x][%x][%x]\n",ac[0],ac[1],ac[2],ac[3]);
    printf("[%x][%x][%x][%x]\n",ac[4],ac[5],ac[6],ac[7]);


    unsigned char *p;
    p = (unsigned char *)(&s[0]);

    memcpy(p, ac, (sizeof s));

    printf("\n");
    printf("[%d],[%d]\n",s[0],s[1]);
    
}


```


```


START
[-2],[-3]
[fe][ff][ff][ff]
[fd][ff][ff][ff]

[-2],[-3]


```