OmniAICreator/Qiita-1.07M huggingface dataset:
Decadent Delights: Exploring the World of Chocolate Gift Sets

Sweet Beginnings: Introduction to Chocolate Gift Sets

Chocolate has long been revered as a symbol of indulgence and affection, making chocolate gift sets a timeless choice for any occasion. Whether it's a birthday, anniversary, or holiday celebration, the allure of decadent chocolates never fails to captivate. In this article, we delve into the world of chocolate gift sets, exploring their diverse offerings, irresistible flavors, and the joy they bring to both giver and recipient.

Unwrapping the Temptation: The Allure of Chocolate Gift Sets

Chocolate Gift Set Varieties: From classic assortments of milk and dark chocolates to artisanal creations featuring exotic flavors and textures, chocolate gift sets come in a variety of enticing options.

Occasions for Gifting: Explore how chocolate gift sets are perfect for birthdays, weddings, holidays, corporate events, and more, adding a touch of sweetness to every celebration.

Personalized Options: Delve into the world of personalized chocolate gift sets, where custom engravings, message cards, and packaging options elevate the gifting experience to a whole new level.

The Art of Selection: Choosing the Perfect Chocolate Gift Set

Quality Matters: Learn how to discern the quality of chocolate based on cocoa content, origin, and production methods, ensuring that your gift delights the senses.

Consider Dietary Preferences: Explore chocolate gift sets tailored to specific dietary preferences, including vegan, gluten-free, and sugar-free options, catering to diverse tastes and needs.

Pairings and Combinations: Discover the art of pairing chocolates with complementary flavors such as wine, cheese, fruits, and nuts, creating a sensory experience that tantalizes the taste buds.

A Feast for the Senses: Experiencing Chocolate Gift Sets

Savoring the Moment: Dive into the sensory experience of indulging in a chocolate gift set, from the rich aroma that fills the air to the velvety smoothness that melts on the tongue.

Exploring Flavor Profiles: Delight in the diverse flavor profiles offered by chocolate gift sets, ranging from the intense bitterness of dark chocolate to the creamy sweetness of milk chocolate, each offering a unique taste sensation.

Texture and Mouthfeel: Explore the importance of texture in chocolate appreciation, from the snap of a perfectly tempered bar to the silkiness of a ganache-filled truffle, enhancing the overall enjoyment.

Gifting with Grace: Etiquette and Presentation Tips
Thoughtful Presentation: Learn how to present chocolate gift sets with elegance and flair, incorporating decorative accents, ribbons, and bows to elevate the visual appeal.

Timing and Delivery: Discover the importance of timing when gifting chocolate, ensuring that the recipient receives their gift at the peak of freshness for maximum enjoyment.

Thank You Notes: Explore the etiquette of expressing gratitude for chocolate gifts, whether through handwritten notes, phone calls, or personalized messages, fostering meaningful connections.

Read More:  https://godivauae.com/collections/summer-collection
ヒストグラムをマルチガウシアンでフィッティングするシンプルな方法

## 対象読者
* Pythonの基本文法を知っている人
* ヒストグラムを複数のガウス関数の和でフィッティングしたい人

## 序論
とある実験の結果として２つ以上のピークがありそうなヒストグラムを得たため、ガウス関数の和でフィッティングしようと思いました。方法をググってみたのですが、検索結果のスクリプトは複雑そうなものでした。そこで、よりシンプルなものを作成したので共有します。基本文法以上の部分には解説を加えました。

## スクリプト
```Python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import norm
from scipy.optimize import curve_fit


# ガウス関数の定義
def gauss(x, *p):
    v = np.zeros_like(x)
    for igauss in range(0, int(len(p) / 3)):
        v += p[3*igauss] * np.exp(-(x - p[3*igauss+1]) ** 2 / (2 * p[3*igauss+2] ** 2))
    return v
    

# データの作成
hist, bin_edges = np.histogram(data, bins=20)
bin_center = [(e1 + e2) * 0.5 for e1, e2 in zip(bin_edges[:-1], bin_edges[1:])]

# フィッティング
popt, _ = curve_fit(gauss, bin_center, hist, p0=[10.0, 0.0, 0.1, 5, 0.5, 0.1])

# グラフの描画
## 棒グラフ
plt.bar(bin_center, hist, width=0.8 * (bin_center[1] - bin_center[0]))

## フィッティングカーブのデータ取得
x = np.arange(0, 2, 0.01)
y1 = gauss(x, *popt[:])
y2 = gauss(x, *popt[:3])
y3 = gauss(x, *popt[3:])

## フィッティングカーブの描画
plt.plot(x, y1, c='red')
plt.plot(x, y2, c='red')
plt.plot(x, y3, c='red')

## グラフの出力
plt.show()
```

## 出力例
![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23570/60bee167-4269-b4cb-57bb-8c2fb961b23e.png)

## 解説
### ガウス関数の定義
```python
def gauss(x, *p):
    v = np.zeros_like(x)
    for igauss in range(0, int(len(p) / 3)):
        v += p[3*igauss] * np.exp(-(x - p[3*igauss+1]) ** 2 / (2 * p[3*igauss+2] ** 2))
    return v
```
ポイントはこの関数の第２引数です。引数名の前にアスタリスクをつけることで、任意の数の位置引数を受け取れるようにしています。３個のパラメータを受け取ったときには1つのガウス関数で、６個のパラメータを受け取ったときには2つのガウス関数の和を、というように受け取るパラメータの個数に応じてガウス関数の個数を自動変更する仕様にしました。シンプルさ重視で、３の倍数以外の個数のパラメータが指定された場合の対応は実装していません。

### データの作成
```python
hist, bin_edges = np.histogram(data, bins=20)
bin_center = [(e1 + e2) * 0.5 for e1, e2 in zip(bin_edges[:-1], bin_edges[1:])]
```
numpyのhistogram関数の出力は、ヒストグラムと、ビン端の値です。２行目で、ビン端の値からビン中央の値を計算しています。２行目は中級者向けのイディオムで、リストの要素をひとつずらして足し合わせることで、ある要素と次の要素の平均を計算しています。

### フィッティング
```python
popt, _ = curve_fit(gauss, bin_center, hist, p0=[10.0, 0.0, 0.1, 5, 0.5, 0.1])
```
gauss関数は任意の数のパラメータを受け取ります。ここではp0に6つのパラメータを渡しているので、2つのガウス関数の和でフィッティングが行われます。3n個のパラメータを渡すと、n個のガウス関数の和でフィッティングが行われます。

## フィッティングカーブのデータ取得
```python
x = np.arange(0, 2, 0.01)
y1 = gauss(x, *popt[:])
y2 = gauss(x, *popt[:3])
y3 = gauss(x, *popt[3:])
```
２行目以降のgauss関数の呼び出しで、第２引数にアスタリスクがついていることに注目してください。こうすることで、リストのスライスを展開して複数の引数としてgauss関数に渡します。gauss関数の第２引数はアスタリスクつきで定義されているので、複数の引数をタプルとして受け取ります。
議事録が苦手なので生成AIに作成させる

議事録を取るのが嫌い・苦手な皆さんこんにちは
私も議事録取るのが嫌いです

嫌いな理由は以下の通り
・録音録画で良くない？手作業でやる意味がわからない
・どうせ書いても誰も読まない
・ファシリテーターが下手だと話題があっちこっちいって大変
・誤字脱字記載漏れがあると詰められる
・タイピングが遅いので会議に追いつけない

ということで大切な作業だというのは理解しつつ、いやなことはテクノロジーで解決しよう！ということでやってみます

::: note
この記事を最後まで読んで頂いても議事録を自動化は出来ません
まだ議事録は人類が取る必要あります
:::

# 前提条件・補足
・2024/05/15にGPT-3.5からChat GPT-4o使用する前提に変更
・Chat GPT-4から添付ファイルの使用が可能になった（ただし有料版のみ使用可能）
・Chat GPT-4oが公開され無料でChat GPT-4以上に高性能な要約が可能になった


# 議事録を作成する手段
・ケース１：会議ツール内で解決する
・ケース２：会議ツール以外で解決する

## 議事録作成のステップ  
そもそも議事録作成するにはどんな作業が必要なんだろう？ということで考えてみます
・STEP１：音声データを文字データに変換する
会議内で話した内容をヌケモレなく文字データにする必要があります
手作業でやっている場合はノートやテキストエディタなどにメモしてる作業です
・STEP２：文字データを決まった議事録形式に要約する
所属組織によって決まったフォーマット、ファイル形式などあると思うので任意のフォーマットで出力する必要があります
個別に検討・評価必要なポイントだと思います

# ケース１：会議ツール内で解決

とりあえず議事録 自動化とかでググると以下のようなサイトがあります
詳細はリンク先を見てもらいたいですが、企業単位で導入するならともかく個人的に議事録取りたくないで導入するのは厳しそうです

![ai-giji_1742_zukai_20240423.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137987/70a14614-edf1-9d84-65c8-37e229886613.png)

参考

https://www.aspicjapan.org/asu/article/1742

## Teamsの機能

Temasには会議を録画する機能や文字起こしする機能が有りましたが、要約する機能が追加されたようです

https://support.microsoft.com/ja-jp/office/microsoft-teams-%E3%81%A7%E3%81%AE%E4%BC%9A%E8%AD%B0%E3%81%AE%E8%A6%81%E7%B4%84-c2e3a0fe-504f-4b2c-bf85-504938f110ef

会社の契約の問題かリリース上の問題かAI要約機能は試せませんでした
また会議の要約と議事録だと用途も違うので不十分に感じます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137987/ab82658d-5a0f-5a07-97ba-2dd4fbd237ec.png)


https://www.microsoft.com/ja-jp/microsoft-365/business/compare-all-microsoft-365-business-products?ocid=cmmi7zvnre9

## ZOOMの機能

こちらも設定で会議の文字起こしは可能ですが、議事録を作成する機能はありませんでした

# ケース２：会議ツール以外で解決
## STEP１：音声データを文字データに変換する
上記の通り、文字起こしの機能はあるので精度はともかく会議ツールの機能内で可能
TeamsのTranscriptファイルを見ると誰が話したかはTeamsアカウントを元に判断するのでオンサイトで開催すると誰の発言か判断できなくなります
## STEP２：文字データを決まった議事録形式に要約する

以下のプロンプトを使用して会議メモ（文字起こしデータ）を要約して議事録を作成します

```
以下の[#会議メモ]は会議音声の文字起こしデータです。
次の[#制約条件]に従って、[#会議メモ]を以下の[#形式]で要約してください。​
[#会議メモ]は添付ファイルを参照ください。

#形式​
・会議のタイトル
・会議のアジェンダ
​・会議参加者
・決定事項​
・ToDo​

#制約条件
​・決定事項、Todoは重要なキーワードを取りこぼさない。
​・期日が明確に設定されている場合は、省略せず文章中に記載すること。
​・文章の意味を変更しない。名詞は言い換え・変換しない。
​・架空の参加者、表現や言葉を使用しない。​
・ToDoは以下のフォーマットに合わせること。​
　[Todo内容] ([Todoの担当者名])​

```

# 評価
## 全体的な感想
正式な議事としてはどうかと思うがルールに従ってちゃんとそれっぽいものは作ってくれた
生成AIの技術的な課題は年内にも改善されそうだが、人間側でも会議の進め方やマイクの設備など気をつけるポイントはある

## 課題：生成AI
### フォーマットがMarkdown形式
主要な生成AIサービスの出力はMarkdown形式で表示されると思います
これをエディタなどに貼り付けてOKが貰えればいいですが、所定のワードやエクセル形式に出力するのは難しいように思います
ワード形式で出力をお願いするとエラーになり、ダウンロード出来ない（作成はしてくれている）
マークダウンファイルをいくつか手間を掛けてワードに変換することは可能

ツールを使う場合

https://qiita.com/tenten0213/items/f67f5601cbed6ef86b3c

ツールを使わずHTMLなどを経由する場合

https://github.com/Takenori-Kusaka/MarkdownToDocx

## 課題：会議ツール
### 会議参加者・会議名が不明
TeamsのTranscriptファイルにはその会議の参加者やタイトルが出力されないのでわからなくなる
タイトルは会議の中でそれっぽい発言があれば生成AIが補完してくれる

### 個別名称の間違い
文字起こしの段階で社内用語などを間違うと修正が出来ない
一般的な用語であれば補正してくれる

# その他参考

議事録の取り方

https://kanataw.com/knowledge/all/becoming-a-consultant/consultant-work-technique/evolution-of-meeting-minutes/

トークン制限
トークンの制限数はGPTのバージョンによって今後変わっていきますが、トークンの考え方の参考に

https://bocek.co.jp/media/exercise/chatgpt/1331/
Windows から Ubuntu の共有フォルダにアクセスできない場合（現在、指定されたネットワーク フォルダーは異なるユーザー名とパスワードを使って割り当てられています。編）

ピンポイントな解決策ですいません

# 事象
Ubuntu PC のネットワークを別のサブネットの部屋に移動したら
Windows PC から Ubuntu の共有フォルダにアクセスできなくなった
共有フォルダは Ubuntu GUI 上でフォルダ右クリックし、「ローカルネットワーク共有」したもの

# 特徴
・同一サブネットの別の Ubuntu PC の共有フォルダにはアクセスできる。

・TeraTerm で Ubuntu PC に接続できる。
・Ubuntu はネットワークに接続しており、Firefox から YouTube 等の外部サイトにアクセスできる。
・プロキシ設定は問題無い。Ubuntu 設定上で「自動」

・Windows「ネットワークドライブの割り当て」で
「別の資格情報を使用して接続する」にチェックを入れ、再割り当てすると
「現在、指定されたネットワークフォルダは異なるユーザー名とパスワードを使って
割り当てられています。異なるユーザー名とパスワードを使って接続するには、
最初に現在のネットワーク共有の割り当てをすべて切断してください。」
というエラーポップアップが表示される

参考　下記では解決できない
・Windows/Ubuntu PC 再起動
・「Windows機能の有効化または無効化」で「SMB1.0/CIFSファイル共有のサポート」をオンにして PC 再起動（セキュリティ的に良くない設定らしい）
・Ubuntu PC で別の名前の共有フォルダを新規作成しても Windows からアクセスできない
・Ubuntu 設定「共有」でメディア共有の有効無効によらない

# 解決方法
Windows PC でコマンドプロンプトや Power Shell のコンソール上で
```
> net use
```
と入力すると、接続したい共有フォルダが「リモート名」に表示される

そのリモート名を下記の削除オプションで消す
```
> net use [リモート名] /delete
例）
> net use \\xx.xx.xx.xxx\share /delete
```
※ IPアドレス やディレクトリのバックスラッシュは円マークかも

その後、再度 Windows「ネットワークドライブの割り当て」で
「別の資格情報を使用して接続する」にチェックを入れ、再割り当てする

終
【Suno AIでつくった楽曲】母の日に贈る1950-1960年代風ポップソング( 中村八大のオマージュ )【動画 1分13秒】【YouTubeチャンネルからの転記です】

この記事は、わたしの[YouTubeチャンネル](https://bit.ly/Yamanaka-YouTube "Living without things. 持たない生き方 手放す生き方")にある公開動画を転記しております。
( どこかのタイミングで、プログラミング-Google Apps Script or iPaaS-Zapier をつかって自動転記させる予定です )

転記のための時間コストを少なくしたいので、文字装飾( Markdown記法 )を極力つかわずに書いております。

こちらが動画内容です👇

***

![100 サムネイル 【Suno AIでつくった楽曲】母の日に贈る1950-1960年代風ポップソング( 中村八大のオマージュ )【動画 1分13秒】 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386308/a5b84ddc-a254-4fb2-a53e-eeb0f5dc88a6.png)



* # 動画URL
    * https://youtu.be/R68XsRde_MM

<br>

* # 動画タイトル
    * 【Suno AIでつくった楽曲】母の日に贈る1950-1960年代風ポップソング( 中村八大のオマージュ )【動画 1分13秒】

<br>

* # 動画の説明欄(一部を抜粋)

📅撮影日 = 2024-04-23(火)

Suno AIとは、文章から音楽を生成することができるAI( Text-to-Music-AI )です。
わたしは、2024-04-02(火)に初めてSuno AIで有償プランを契約してから、時々楽曲をつくって遊んでいます。

🎦【Suno AI】文章から音楽を生成するAI( Text-to-Music-AI )で、3分間で2曲、6分間で4曲作りました【試聴可能】1)伴侶の曲 2)税理士の曲【動画 16分11秒】
https://youtu.be/QKfhk4HgQ_g

🎦“Suno AIでつくった楽曲”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe

🎦“効果的にSuno AIを活用するヒント”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


今回は、Suno AIでつくった曲をMP3で出力してから、動画編集いたしました。
ぜひ聴いてみてください。
そして、ぜひみなさんも、あなたがつくった楽曲を愛する家族に贈ってみてください！

作曲日:
2024-04-23(火)

契約の種類:
Pro Plan

楽曲の正式名称:
母の日に贈る歌 2024年版

Suno AI Library URL:
https://bit.ly/suno-Mothers-Day-Song-2024

With Vocals:


---


Lyrics:

[Verse]
ありがとう母さん 心からの
感謝の気持ち 伝えたいんだ
君の優しさ わかるよ母さん
いつも側にいてくれた

[Verse 2]
長い夜も 共に過ごして
悲しい時も 笑顔で包んでくれた
どんなことも 乗り越えられる
母の愛が 僕を支えている

[Chorus]
母への贈り物 歌に込めて
心からの愛が 届きますように
母への感謝を 歌に乗せて
永遠の愛を 届けたい


---


Suno AIへの指示文章( プロンプト/Prompt ):


🇯🇵日本語

次の母の日に、自分の母へ贈る楽曲をつくってほしい。
曲の長さ：60秒間前後。
楽器：ヴォーカルとザイロフォン( 木琴 )のユニゾン。
1950-1960年代に流行したような曲調のポップス。バラード。
次の作曲家、編曲家が手掛けたような雰囲気 1)中村八大 2)バート・バカラック 3)筒美京平。
リードヴォーカルは男性。コーラスは男性2人、女性2人


🇬🇧English Translation

For Mother's Day, I want to create a song as a gift for my mom.
The song should be about 60 seconds long.
It should feature vocals and xylophone in unison.
The style of the music should be similar to the pop ballads popular in the 1950s and 1960s, reminiscent of compositions by Hachidai Nakamura, Burt Bacharach, and Kyu Sakamoto.
The lead vocalist should be a male, with a chorus of two men and two women.


---


Suno AI 公式URL
https://accounts.suno.ai


---


✓ 🎥この動画と関連が強いわたしの動画 ↙
　・“Suno AIでつくった楽曲”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe


　・“効果的にSuno AIを活用するヒント”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


✓ 🎥Shortened URL for this video | この動画の短縮URL ↙
　https://bit.ly/3xObAb4
cloud9でpgAdminのDockerコンテナーの起動方法（PostgreSQLにGUIでアクセス）

# はじめに
DBにアクセス制限があって、cloud9でしかアクセスできない場合に、psqlなどcommand-lineでアクセスすると、しにくいだと思いました。GUIでアクセスできるツールがあるかを探したら、pgAdminが見つかりました。

# 参考リンク
[Introduction PostgreSQL: pgAdmin](https://catalog.us-east-1.prod.workshops.aws/workshops/2a5fc82d-2b5f-4105-83c2-91a1b4d7abfe/en-US/5-opensource/lab9-postgres-introduction/task1)

# 構築手順
### Dockerコンテナーのデータ保存のため、フォルダを作成
```
cd ~/environment
mkdir pgadmin
sudo chmod -R a+rw pgadmin
```

### pgadminのDocker imageをダウンロード
```
docker pull dpage/pgadmin4
```

### Dockerコンテナーを作成
- [ログイン用のメール]と[ログイン用のパスワード]は好きなメール、パスワードをリプレイスしてください
```
docker create -p 8080:80 \
    -e "PGADMIN_DEFAULT_EMAIL=[ログイン用のメール]" \
    -e "PGADMIN_DEFAULT_PASSWORD=[ログイン用のパスワード]" \
    -v /home/ec2-user/pgadmin:/var/lib/pgadmin \
    --name pgadmin \
    dpage/pgadmin4
```

### Dockerコンテナーを起動
```
docker start pgadmin
```

### アクセスURLを取得
```
echo https://${C9_PID}.vfs.cloud9.$AWSREGION.amazonaws.com/
```
- https://xxxx.vfs.cloud9.ap-northeast-1.amazonaws.com/ みたいなURLが表示されます

### ブラウザでURLにアクセス
- pgadminのwebが表示されます
- さっき使ったメール、パスワードを入力してログインしてください
- pgAdminの詳しい使い方はここで説明しません
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951526/a669bcdf-c055-79b6-7beb-a1c5287ee6a4.png)
【MT4 EA MQL4】parameter conversion not allowed. invalid array access.

## Error statements
+ parameter conversion not allowed. 
+ invalid array access.

## Cause & Solution
```c++
int array[][]  ====>>>  int array[] 
```

It appears that multidimensional arrays are prohibited as function arguments. Please use a one-dimensional array.
多次元配列は関数の引数として禁止されているようです。知らんけど。一次元配列を利用してください。
AdminLTEで左メニューを非表示にする方法

## AdminLETでコンテンツ部分のみ表示させたいことがあったので、以下の方法で試しました。
### 前提条件
- AdminLTEはv3です。
- CSSを直接編集することはしたくなかったので、html上に直接 styleタグ として記述しました。

## やったこと

まずは余分な箇所を非表示
```
aside.main-sidebar {display: none;} /* メニューを非表示 */
nav.main-header {display: none;} /* ヘッダーを非表示 */
div.content-header {visibility: hidden;} /* パンくずを非表示 */
```

パンくずは display:none だと上部のマージンがなくなってしまったので、visibility:hidden としています。

ただ、これだけでは、メニュー部分が空白で残ってしまうので、以下も必要です。
```
div.content-wrapper {margin-left: 0 !important;} /* コンテンツ部分のマージンを削除 */
```
content-wrapper の margin-left はメディアクエリーで定義されているので、!important が必要でした。

けっこう力技なので、もっと良いやり方ありそうですが、実現するにはこれでいけました。
Railsテスト環境でのSQLクエリログの表示方法


### ステップ1: 設定ファイルの開き方
まず、Railsプロジェクト内の`config/environment/test.rb`ファイルを開きます。このファイルには、テスト環境の設定が含まれています。

### ステップ2: 設定の変更
ファイル内で、以下のコードスニペットを追加します。

```ruby
config.logger = ActiveSupport::Logger.new(STDOUT)
config.log_level = :debug
```

このコードは、ログを標準出力（コンソール）に書き出すようにロガーを設定します。

### ステップ3: ファイルの保存
変更を加えた`test.rb`ファイルを保存します。

### 結果
以上のスニペットを設定ファイルに追加することで、テスト環境でテストを実行する際にSQLクエリログがコンソール出力に表示されるようになります。これにより、テストプロセス中に実行されるSQLクエリを監視し、分析することができます。
【SwiftUI】よくある TextField を作る


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【SwiftUI】TextField の角を丸くして背景色を付けるもっとも簡単な方法は<br>👉 <a href="https://t.co/LpqABKBpQA">https://t.co/LpqABKBpQA</a><a href="https://twitter.com/hashtag/ios?src=hash&amp;ref_src=twsrc%5Etfw">#ios</a> <a href="https://twitter.com/hashtag/macos?src=hash&amp;ref_src=twsrc%5Etfw">#macos</a> <a href="https://twitter.com/hashtag/swift?src=hash&amp;ref_src=twsrc%5Etfw">#swift</a> <a href="https://twitter.com/hashtag/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0?src=hash&amp;ref_src=twsrc%5Etfw">#プログラミング</a></p>&mdash; chanzmao (@maochanz) <a href="https://twitter.com/maochanz/status/1787733069216280686?ref_src=twsrc%5Etfw">May 7, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こう書いてみました。

```swift
RoundedBorderTextField(label: "Search", text: $text)
  .frame(width: 200)
```

![sc 2024-05-08 at 14.44.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588914/9fe5c320-26b8-80b2-deb8-81a29ec4a54b.png)

```swift
struct RoundedBorderTextField: View {
  var label: String
  @Binding var text: String

  private let rect = RoundedRectangle.rect(cornerRadius: 6)

  var body: some View {
    TextField(label, text: $text)
      .textFieldStyle(.plain)
      .padding(6)
      .background(.background, in: rect)
      .overlay(rect.stroke(.secondary, lineWidth: 0.5))
  }
}
```
Android Studioをアップグレードするときのkeymapなどの設定を保持する方法

Android StuidoのJellyfishがstableになりました🎉
iguanaのstable releaseから2ヶ月くらいしか経っていないような気がします。早いですね。

新しい環境は非常にありがたいですが、前回もなんとなくアップデートしてkeymapが移行できず、またダウングレードしてからやり直していたので、簡単ですがメモとして残します。

まずアップデートする前に、設定ファイルをエクスポートしておきましょう。

File -> Manage IDE Settings -> Export Settingsとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165483/9c06fea3-d540-14c1-3ac1-20584d0733cd.png)

次にアップデートすると、keymapが変わってしまうことがあるようです。自分はカスタムのkeymapを作っているのですが、強制的にmacOSというテンプレートに戻ってしまっていました。

エクスポートしたのと同じ手順で、今度は`import Settings`を選びます。

keymapだけでなく、自分でカスタマイズしてツールバーに置いたボタンなども保持することができました。
GitLabで使うコマンド集【ビギナーなので】

## 基本的なGitコマンド

- **git clone [url]**  
  リポジトリをローカルマシンにクローンするコマンド。
  ```
  git clone [url]
  ```
  <br>
  
- **git pull [remote] [branch]**  
  リモートリポジトリの特定のブランチから変更を取得して、ローカルブランチとマージする。
  ```
  git pull [remote] [branch]
  ```
  <br>
  
- **git push [remote] [branch]**  
  ローカルの変更をリモートリポジトリの指定されたブランチにプッシュする。
  ```
  git push [remote] [branch]
  ```
  <br>
  
- **git fetch [remote]**  
  リモートリポジトリから最新の履歴を取得するが、ローカルのブランチにはマージしない。
  ```
  git fetch [remote]
  ```
  <br>
  
- **git add [file]**  
  指定したファイルをステージングエリアに追加する。
  ```
  git add [file]
  ```
  <br>
  
- **git commit -m "message"**  
  ステージングされた変更に対してコミットを作成する。
  ```
  git commit -m "message"
  ```
  <br>
  
- **git status**  
  ローカルリポジトリの状態を表示する（変更されたファイル、ステージングされた変更など）。
  ```
  git status
  ```
  <br>
  
- **git log**  
  コミット履歴を表示する。
  ```
  git log
  ```
  <br>
  
- **git checkout [branch-name or commit-hash]**  
  特定のブランチやコミットに切り替える。
  ```
  git checkout [branch-name or commit-hash]
  ```
  <br>
  
- **git branch [branch-name]**  
  新しいブランチを作成する。
  ```
  git branch [branch-name]
  ```
  <br>
  
- **git merge [branch]**  
  指定したブランチを現在のブランチにマージする。
  ```
  git merge [branch]
  ```
  <br>
  
## 応用的なGitコマンド

- **git stash**  
  ワーキングディレクトリの変更を一時的に保存して、ワーキングディレクトリをクリーンな状態に戻す。ブランチを切り替える必要があるが、現在のブランチで完了していない作業を保存しておきたい場合に便利みたいです。
  - `git stash apply` で保存した変更を再適用できる。
  ```
  git stash
  ```
  ```
  git apply
  ```
  <br>
  

- **git rebase [basebranch]**  
  指定したブランチ（basebranch）を現在のブランチの新たなベースとして適用して、コミット履歴を整理する。マージと異なって、きれいな履歴を作成するのに良いらしい。
  ```
  git rebase [basebranch]
  ```
  <br>

- **git cherry-pick [commit]**  
  別のブランチの特定のコミットを現在のブランチに適用できる。これによって、特定の変更だけを取り込むことが可能になる。
  ```
  git cherry-pick [commit]
  ```
  <br>

- **git reset [file]**  
  ステージングされた変更を取り消して、ファイルを以前のコミットの状態に戻す。オプションによっては、ワーキングディレクトリの変更も取り消すことができるようですが、resetとつくコマンドはよく調べたほうが良さそうですね。
  - `git reset --hard [commit]` で現在のブランチのHEADを指定したコミットにリセットして、ワーキングディレクトリもその状態に戻せる。
  ```
  git reset [file]
  ```
  ```
  git reset --hard [commit]
  ```
  <br>

- **git bisect [bad commit] [good commit]**  
  バグが導入されたコミットを二分探索法を使用して特定する。基本情報技術者試験で出てきた二分探索法。資格の勉強が少し役に立ちました。このコマンドは、特定の問題が発生した正確な変更点を見つけるのに有効的だそうですね。
  ```
  git bisect [bad commit] [good commit]
  ```
  <br>
  

- **git blame [file]**  
  ファイル内の各行がどのコミットで追加されたかを表示する。変更の過程を調査するときに役立に立ちます。
  ```
  git blame [file]
  ```
  <br>

- **git diff [branch1] [branch2]**  
  二つのブランチ間での差分を表示する。ファイルごとに変更内容を確認できます。
  ```
  git diff [branch1] [branch2]
  ```
  <br>

- **git tag [tagname] [commit]**  
  特定のコミットにタグを設定して、バージョンリリースなどの重要なポイントをマークできる。
  ```
  git tag [tagname] [commit]
  ```
  <br>

---
最近はCLIでなくGUIでの操作が主流？なような気がしますが、忘れたと起用にコマンドを残しておきます。
【visionOS】Buttonの標準の背景色を透明にする

本記事では、visionOSでButtonの標準背景色を透明にし、背景色をカスタマイズする方法について説明します。

(※技適特例届け出済み)

## 問題

Buttonに`.background(Color.clear)`を指定しても、楕円形の背景色が残ってしまいます。

```swift
Button(action: { }) {
   ZStack {
       Circle()
           .frame(width: 60, height: 60)
           .foregroundStyle(.gray)
       Image(systemName: "square.and.arrow.up")
           .resizable()
           .aspectRatio(contentMode: .fit)
           .frame(width: 22)
   }
}
.background(Color.clear)
```

<img width="320" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1042576/1d5eb747-6a79-a353-92f5-55ed43d4baba.png">


## 解決方法

この問題は、以下のように`.buttonStyle(.plain)`を指定することで解決できます。


```swift
Button(action: { }) {
    ZStack {
        Circle()
            .frame(width: 60, height: 60)
            .foregroundStyle(.gray)
        Image(systemName: "square.and.arrow.up")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 22)
    }
}
.buttonStyle(.plain)
```

<img width="320" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1042576/582bd58a-9a66-ad9b-4897-019807c5e5d8.png">

`.buttonStyle(.plain)`を指定することで、標準の背景を削除し、透明な背景を実現できます。これにより、自由にButtonの背景色をカスタマイズすることが可能になります。
How to write proxy ID & password, including special characters （特殊文字を含む場合のproxy認証）

前置き
---
会社のproxyがこの春に更新され、emailをIDとして使うようにお達しがおりました。困ったことにemailには　**@** が含まれており、Linuxではproxy認証が通りません。
一方、windowsでは、このような特殊文字も問題なく利用できるようで、社内で苦情を言う人はほぼ私一人でした。
苦情を申し立てても無視されてしまい、独力で解決方法を探した次第。

この件は日本語の記事が少ないようですが、数年前に[**ここ**](https://qiita.com/nshinya/items/08db9be2c5255c91e6a0)に記載がありました。それを補足するのがこの記事です。windowsではおそらく不要です。（macはどうなのかな？　homebrewでは必要かもしれませんね。）

Special Character（特殊文字）のpercent encoding
---
下記に記載した[**wiki**](https://en.wikipedia.org/wiki/Percent-encoding)をご覧いただくと、中程に**Reserved characters after percent-encoding** なる表があります。必要なのはこれです。これに沿って特殊文字を変換します。

```
## Original
ID        : 123.zz@abc.com
password  : Abc123# 

## eocodings of special character
@ : %40
# : %23

## percent encodings of original
123.zz%40abc.com
Abc123%23

## add to zshrc, bashrc...
# proxy:192.168.1.1
# port:8080

export HTTPS_PROXY=http://123.zz%40abc.com:Abc123%23@192.168.1.1:8080
```

参照page
---
もう少し複雑な例は[このpage](https://www.cyberciti.biz/faq/unix-linux-export-variable-http_proxy-with-special-characters/)にあります。参照ください。

英語でよければ、以下を読まれると理解が深まると思います。[wiki](https://en.wikipedia.org/wiki/Percent-encoding)は英語の方を読んでください。日本語では肝心な特文字の変換表がありませんので。英語がだめな方は[DeepL](https://www.deepl.com/ja/translator)などを利用されては如何。

https://superuser.com/questions/273799/how-to-use-special-characters-in-username-password-for-http-proxy

https://en.wikipedia.org/wiki/Percent-encoding

https://www.cyberciti.biz/faq/unix-linux-export-variable-http_proxy-with-special-characters/



お願い
---
上記でも駄目なのが[**w3m**](https://wiki.archlinux.jp/index.php/W3m)です。optionのpageを開いて、いろいろ試しましたが、どうしてもproxy認証が通りません。

上記以外の原因で、proxyとのnegotiationがうまくいかない可能性が高いので、logを見直してしてみます。
もしどなたか解決策をご存知でしたらお教えください。

```sh
# proxy repose.
### using percent encodings.
Username for Web-Proxy Server:  123.zz%40abc.com
Password for Web-Proxy Server: ****** 
....
Wrong username or password
```
【Unity】Git 初心者でもできる個人開発で Git 管理を行う簡単な方法

皆さんは個人開発でも GitHub を活用していますか？

Git が共同開発において
強力な武器になるのは言うまでもないですが
個人開発でバックアップを
効率的に取る方法として考えたとしても
非常に優れています。

Git でバックアップを取らない場合は
バックアップは非常に大変な作業になります。

例えば 100MB のプロジェクトがあったとして
6KB のファイルを編集したとします。
この時プロジェクト全体のバックアップを
再度取った場合は 100MB の容量が増えます。

編集したファイルだけバックアップを取るのは
古いファイルの管理が大変になります。

そこで是非とも皆さんには個人開発で
GitHub を使って頂きたいと思うのです。

...と言いたい所ですが
果たして本当に GitHub が必要でしょうか？
これから考えてみましょう。

***

GitHub は本当に必要か

結論から言います。
特に理由が無い場合は
個人開発のプロジェクトで Git を使う場合は
Git をローカルに保存すれば OK と思います。
GitHub を活用する必要はないと思います。

Sourcetree だけで完結しておけば
面倒な作業が減ると思います。

GitHub との連携は
それほど複雑ではないかもしれませんが
私は大きなメリットを見いだせないのです。

特にテスト用など小規模プロジェクトで
毎回 GitHub と連携する必要は全くないと思います。
これから GitHub を使わずに
ローカルで作業する場合の手順を見て頂きます。

***

個人開発で Git 管理を行う最低限の方法について

以下の手順だけで済みます。
Unity のプロジェクトは既に作成しているものとします。

1. Sourcetree をインストールします。(初回のみ)
2. Create a repository で
　プロジェクトの「Assets」フォルダを設定します。
3. コミットして後は通常通り操作します。

これだけの手順で OK なのです。
Assets フォルダだけを選択すれば
.ignore を設定する必要はありませんし
Assets フォルダ以外を編集する機会は意外とありません。

編集する場合に初めて
.ignore を考慮すれば良いのです。

Package Manager でインストールした物は
再インストールすれば OK です。

これらの手間よりも
初心者の方が Git 環境の構築が複雑で
Git を諦める方が問題だと思うのです。

また Git は「プル」「コミット」等
操作が多く、初心者の方は敬遠するかもしれません。
しかしながら「コミット(バックアップを取る)」と
「現在のブランチをこのコミットまでリセット(バックアップを読み込む)(Hard)」の
2 個の操作のみ覚えておけば
使わないよりは有効活用できます。

これらの操作は簡単なため
初心者の方は敬遠しないで
是非とも使って頂きたいのです。

***

必要な操作のまとめ

最低限必要な操作は

1. SourceTree のインストール
2. リポジトリの作成
3. コミット(バックアップを取る)
4. 現在のブランチをこのコミットまでリセット(バックアップを読み込む)(Hard)

の 4 点です。

その内 2 ～ 4 は
慣れれば 20 秒以内で操作できる作業量です。

Git による管理は
最低限必要な操作だけに絞れば
作業量が意外と少ないのです。

***

まとめ

以上、個人開発で Git 管理を行う
最低限の方法について紹介しました。

この記事は初心者の方に
Git を敬遠しないで欲しいという意図で
作成しております。

この方法ならば簡単に操作できます。
是非 Git を使っていない方は
まずはこの方法で使って頂けると嬉しいです。

個人開発でも Git は強力な武器です。
是非とも初心者の方に使って頂きたいと思います。

皆さんの開発の助けになれますように。
閲覧ありがとうございました。

***

追記

具体的な手順を説明する記事を
1 個書きました。

この記事を参考にして
失敗した際はご覧頂けると幸いです。

[https://qiita.com/uni928/items/8a560522e4ce1f2bdcde](https://qiita.com/uni928/items/8a560522e4ce1f2bdcde)

上記の記事を見る前に
まずはご自身で試して頂いた方が
習得作業としては良いと思われます。

上記の記事は完全に
手順のみを記載しております。
知見を得るためにこの記事を読んだ方にとっては
得るものが無いかもしれません。

実践して失敗した方のみ
閲覧して頂く形式で OK と思います。
diagramsを使ってAWS構成図を書こうと思ったが導入でつまずいた話

AWSの構成図をPythonパッケージのdiagramsを使って書こうと思ったのですが、意外と導入でつまずいたのでまとめます。

## 環境
 - Python 3.8.10
 - pip 23.3.1
 - Windows 11 Pro
 - WSL 2.1.5.0

## 描画用プログラム
```python
from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.onprem.client import Client

with Diagram("Simple Diagram") as diag:
    ec2_pub = EC2('Public Instance')
    ec2_pri = EC2('Private Instance')
    Client() >> ec2_pub
    ec2_pub - ec2_pri

diag
```
中身は何でもいいのですが、ひとまず描画できることを確認するためのものです。

## 導入手順
```
$ pip install diagrams
```

どうやら大抵の人はこれで動くらしいですが、この後上記描画用プログラムを実行すると自分は以下のエラー発生。

```
failed to execute PosixPath('dot'), make sure the Graphviz executables are on your systems' PATH
```

dot コマンドがないってよ。

```
$ dot -V

Command 'dot' not found, but can be installed with:

sudo apt install graphviz
```
確かに無いので、おとなしく言われた通りインストールしてみます。

```
$ sudo apt install graphviz
```
確認
```
$ dot -V
dot - graphviz version 2.43.0 (0)
```
無事インストールできたので、ここで改めて上記描画プログラムを実行します。

```
No such file or directory: 'xdg-open'
```
またエラー。。。

```
$ xdg-open

Command 'xdg-open' not found, but can be installed with:

sudo apt install xdg-utils
```

はい、こちらも入れましょう。

```
$ sudo apt install xdg-utils
```

```
$ xdg-open --version
xdg-open 1.1.3
```

改めて描画プログラムを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777293/5bc43b8b-e6fd-7437-3ee5-bdf4b112b54f.png)

できた！
導入でつまずくと何をしようとしていたのか忘れる...
Github Copilotを$100/yearで課金したはずが$200引かれていた話

# Github Copilotを$100/yearで課金したはずが$200引かれていた
AIによるコーディング支援をしてくれる[Github Copilot](https://docs.github.com/ja/copilot/using-github-copilot/getting-started-with-github-copilot)を個人アカウントで申し込んでみました。利用には課金が必要で個人の場合はCopilot Individual(他にCopilot Individual以外にCopilot BusinessとCopilot Enterpriseがある)を

- 1 か月あたりの$10
- 1年あたり$100

のどちらかを選択して申し込みます。今回は1年あたり$100を選択しGithub Copilotを利用開始しました。

開始してしばらくは無料期間があり、それが終了すると課金開始の連絡がきたので

- [Githubの支払い履歴ページ](https://github.com/account/billing/history)

から確認すると

![Github-billing1 - fix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86684/25220f6d-ed42-63ff-a467-74cf0f9ed1b2.png)

のように$200引き落とされているようでした。

# 問い合わせてみる

\\$100/year のはずが$200なのは謎なので問い合わせをしてみました。問い合わせは

- [GitHubについてのお問い合わせ](https://support.github.com/contact?source=subtitle&tags=rr-general-technical)

からチケットを作成する形でできます。今回は以下のような内容で問い合わせをしてみました。

```
Github Copilotの課金を開始したところ
https://github.com/account/billing/history
にて確認すると初回の支払いが$200.00の支払いになっているようです。

年単位の支払いサイクルを選択したので、利用料金は$100/yearの認識ですがなぜ$200なのか回答お願いします。
```


これに対して以下のような自動応答のコメントがつき、問い合わせフォームからキャンセル手続きを案内され、チケットもクローズになってしまいました。

```
Hi there,

It looks like your Copilot refund request may be eligible to be handled by our virtual assistant which would get this processed for you immediately.

Can you please try following these steps?:

Follow this specific link to our contact form: https://support.github.com/contact/account?flow=refund_copilot_individual
Scroll down a bit to see a blue button activated to "Try our virtual agent".
Follow the prompts to request the cancellation and prorated refund.
This should automatically process the refund and cancellation and send a confirmation.

We're going to mark this ticket as closed, but if the virtual assistant is not able to help and you need further assistance, please don't hesitate to reply here which will automatically reopen the ticket and we'll get back to you as soon as possible.

Thanks,
GitHub Support
```

しかし、今回はキャンセルをしたかったわけではなく、"なぜ\\$200になっているのか"を知りたかった(私の認識が間違っていたならそのまま$200で使い続けたかった)ので再度チケットをオープンし、

```
キャンセルをしたいわけではなく初回の支払いが$200.00になっている理由を教えていただきたい。
```

と再度チケットにコメントしました。コメントから数日後、支払い処理業者との同期に問題があり払い戻しが実行されるという内容で以下のように回答がありました。

```
Hi there,
 
Thanks for reaching out and my apologies for the trouble. We had a syncing issue with our payment processor, but it has since been resolved.
 
A refund has been issued to the original payment method and those funds should be available within a few business days. The refund receipt has been attached for your records. 
 
Let me know if there are any further questions.
 
Catriana | GitHub Support
```

# まとめ

Github Copilotを\\$100/yearで課金したはずが$200引き落とされてしまうという事態になりましたが、問い合わせをして\\$100払い戻しをしてもらうことができました。このあと再度[Githubの支払い履歴ページ](https://github.com/account/billing/history)から確認したところ

![Github-billing2 - fix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86684/f5c82ff8-f0d0-1be4-32e0-b463ddae78dd.png)

のように\\$-100と払い戻しになり、Github Copilotも問題なく使用できています。
[BigQuery API(V2)] JavaでBigQueryテーブルの行(レコード)を取得する

BigQuery API V2(Java)を使用して、
BigQueryテーブルの行(レコード)を取得する方法
についてご紹介します。

レコードの情報を取得するには、
適切なIAM権限が付与されている必要があります。

権限付与に関しては
[⧉[BigQuery API(V2)] JavaでBigQueryを使う(2.権限付与)](https://qiita.com/doran/items/8b7ba29672527426e88d#2-権限付与)
を参照ください。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[BigQuery API(V2)] JavaでBigQueryを使う](https://qiita.com/doran/items/8b7ba29672527426e88d)
を参照ください。
:::

|No||目次|
|---|---|---|
|1||[レコードを取得](#1-レコードを取得)|
||1|[スコープ](#11-スコープ)|
||2|[実行](#12-実行)|
||3|[レスポンスの内容](#13-レスポンスの内容)|

## 1. レコードを取得
指定したテーブルのレコードを取得します。

### 1.1. スコープ
このAPIを実行するには、以下のいずれかのスコープを指定してください。
```
BigqueryScopes.BIGQUERY
BigqueryScopes.CLOUD_PLATFORM
BigqueryScopes.CLOUD_PLATFORM_READ_ONLY
https://www.googleapis.com/auth/bigquery.readonly
```
[⧉[BigQuery API(V2)] JavaでBigQueryを使う(3.2. BigQueryインスタンスを取得)](https://qiita.com/doran/items/8b7ba29672527426e88d#32-bigqueryインスタンスを取得)
でスコープを指定してください。

### 1.2. 実行

```java
public static void main(String[] args) throws Exception{
    Bigquery bigquery = getBigquery();
    Bigquery.Tabledata tabledata = bigquery.tabledata();
    
    Bigquery.Tabledata.List list = tabledata.list("プロジェクトID","データセットID","テーブルID");
    
    TableDataList res = list.execute();
    System.out.println(res);
}
```
#### 1.2.1. HTTPリクエスト
GET:　https:\//bigquery.googleapis.com/bigquery/v2/projects/{プロジェクトID}/datasets/{データセットID}/tables/{テーブルID}/data
が実行されます。

#### 1.2.2. クエリパラメータ
Bigquery.Tabledata.Listのsetメソッドにより、クエリパラメータを追加できます。

|メソッド|引数|説明|
|---|---|---|
|setMaxResults|Integer|結果の最大数|
|setPageToken|String|取得するページトークン|
|setStartIndex|String|取得する開始行インデックス|
|setSelectedFields|String|取得するフィールド|
|setFormatOptions|[DataFormatOptions](#dataformatoptions)|出力フォーマットの調整|

#### DataFormatOptions
|メソッド|引数|説明|
|---|---|---|
|setUseInt64Timestamp|Boolean|タイムスタンプをusec int64として出力するか|

### 1.3. レスポンスの内容
#### TableDataList
|メソッド|戻り値|説明|
|---|---|---|
|getKind|String|リソースの種類<br>固定文字列："bigquery#tableDataList"|
|getEtag|String|ハッシュ値|
|getPageToken|String|次のページトークン|
|getTotalRows|Long|テーブル全体の合計行数|
|getRows|List\<[TableRow](#tablerow)\>|行情報|

#### TableRow
|メソッド|戻り値|説明|
|---|---|---|
|get("フィールド名")|Object|指定したフィールド名のレコードの値を取得|

<br>
<br>
おしまい。。
リストを２つのカラムでグループ化する




Listのアイコンから

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/4d013085-2114-c2b0-4d1e-cf907d25aeb8.png)

SharePointから

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9353310e-aaf7-427a-ebef-a0b72e4cf97a.png)


# 設定方法

すべてのアイテム --> 現在のビューの編集

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d1a3b783-ca50-b292-0865-26a933c3d9fc.png)

ずっと下の方にスクロール、グループ化を展開

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/397eb738-9829-ca20-3977-a9f5b9582c11.png)

２つのカラムまで指定できるみたい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8f45b21d-7813-1963-a536-824211508ae9.png)
【Python】コンソールにいい感じに文字列を表示させるコード

本記事はPythonのコンソール画面に日本語文字列を表示させるコードを記述したのでその備忘録です。
本コードはPythonの標準ライブラリを使用しているため、Python自体が古すぎなければ問題なく動くはずです。

まずは、本記事を書くにあたり以下を参照しました。

* [Python公式ドキュメント](https://docs.python.org/ja/3/library/unicodedata.html)
* [Pythonで半角1文字、全角2文字として文字数（幅）カウント](https://note.nkmk.me/python-unicodedata-east-asian-width-count/)

# 本コード

```python:printText.py
import unicodedata

def get_string_length(text):
    count = 0
    for c in text:
        if unicodedata.east_asian_width(c) in 'FWA':
            count += 2
        else:
            count += 1
    return count


def insert_char_toString(text, insert_char=' ', text_length=80):
    if(get_string_length(text) >= text_length):
        return text
    return text + insert_char * (text_length - get_string_length(text))


def cut_string_by_length(text, text_length):
    tmp_list = []
    tmp_text = ''
    for idx, c in enumerate(text, 1):
        tmp_text += c
        if(get_string_length(tmp_text) == text_length):
            tmp_list.append(tmp_text)
            tmp_text = ''
        if(get_string_length(tmp_text) == text_length+1):
            tmp_list.append(tmp_text[:len(tmp_text)-1]+' ')
            tmp_text = tmp_text[-1]
        if(idx == len(text)):
            tmp_list.append(insert_char_toString(tmp_text, text_length=text_length))
    return [i for i in tmp_list if i.strip() != '']


def get_split_strings_by_length(texts, text_length=80):
    text_list = []
    for text in texts:
        if text.find('\r\n') or text.find('\n'):
            [text_list.extend(cut_string_by_length(j, text_length)) for j in [i for i in text.replace('\r','').split('\n')]]
        else:
            text_list.extend(cut_string_by_length(text, text_length))
    return text_list


if __name__ == '__main__':

    texts = [
        'unicodedata --- Unicode データベース\r\n\r\n',
        'このモジュールは、すべてのユニコード文字の文字プロパティを定義するユニコード文字データベース (UCD) へのアクセスを提供します。このデータベースに含まれているデータは、 UCD バージョン 15.0.0 から作成されています。',
        'このモジュールは、ユニコード標準付録 #44 「 ユニコード文字データベース 」で定義されているのと同じ名前およびシンボルを使用します。このモジュールは次のような関数を定義します:',
        'unicodedata.east_asian_width(chr)\r\nユニコード文字 chr に割り当てられたeast asian widthを文字列で返します。'
    ]

    print('/**** ' + insert_char_toString('', '-') + ' ****/')
    for string in get_split_strings_by_length(texts):
        print('/**** ' + string + ' ****/')
    print('/**** ' + insert_char_toString('', '-') + ' ****/')
```

## 出力結果

上記コードを実行すると以下のように表示されます：

![出力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3275023/ef98d50f-b60d-d632-d868-62d8a878ad32.png)

## 簡単な説明

* 日本語文字列の長さを調べるために `unicodedata.east_asian_width` を使用。※Pythonでデフォルトで使用可能な `len(text)` 関数は半角も全角も区別せず１文字として認識してしまう。
* コンソールに表示する際の文字列長を `text_length`で制御しており、デフォルト長を `80` としています。
* `text_length` に満たない文字列は長さが `text_length` になるまで半角スペースを挿入しています。
* 改行コードについては、テキストを分割してリストに追加しています。

# まとめ

コンソール表示を綺麗に出力できたので満足。
テキストエディタに張り付けると見た目が悲しくなるので画像で表示するにとどめました。
MQTT の Session State についてざっくり理解する

# Session とは何か
`Client Identifier`（クライアントID）で識別される、クライアントとの接続を一意に表す概念。つまり、同じクライアントIDの接続が2つ以上同時に存在することはできない[^1]。

# Session State とは何か
文字通り、`Session`の状態を指す。以下の2つの状態がある。
- サブスクライブ状態
  クライアントがどのトピックをどの`QoS`でサブスクライブしているか、という情報の集合。
- 未完了のパブリッシュ・シーケンスの状態
  `PUBLISH`パケットや`PUBREL`パケットを送信したが、その応答パケットが返ってきていない、という情報の集合。これは、`QoS1`、`QoS2`にのみ適用される。

ブローカーは、以下の2つのいずれかの条件を満たすとき、`Session State`を維持する。
- クライアントが接続されている
- クライアントが切断されているが、`Session State`の有効期限が切れていない

[^1]:AWS IoTのブローカーの場合、あるクライアントIDを持つクライアントAがブローカーに接続している状態で同一のクライアントIDを持つクライアントBが接続すると、元々接続していたクライアントAの接続が切断される、という動作をする。

# 有効期限の設定方法
MQTTのバージョンで違いがある。
## MQTT V3.1.1の場合
そもそも有効期限の規定がない。
`CONNECT`パケット送信時に`Connect Flags`の`Crean Session`に`0`を指定することで、以前の`Session`があればその`Session`が使用される。1を指定した場合は、それまでの`Session`は破棄され新しい`Session`が作成される。
## MQTT V5.0の場合
MQTT V3.1.1のCrean SessionはMQTT V5.0ではCrean Startに変更されている。また、`CONNECT`パケットの`Session Expiry Interval`のプロパティに秒数を指定することで設定できる。
`Session Expiry Interval`が
- 省略されたとき
  `0`扱いとなる。
- `0`のとき
  ブローカーはクライアントとの切断後に`Session State`を維持しない。
- `0`でないとき
  ブローカーはクライアントとの切断後も指定された秒数だけ`Session State`を維持する。
- `0xFFFFFFFF`のとき
  `Session State`の有効期限は無期限という扱いになる。

# 動作イメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138405/5fee93b6-d0d5-b150-b3b0-c9447a1535d5.png)

クライアントAとブローカーの間で以下のようなやり取りが行われる:

1. クライアントAがブローカーに接続する際、`CONNECT`パケットを送信し、`Session Expiry Interval`を例えば`300`秒に指定する。これにより、クライアントAとブローカー間の接続が切断された後も、ブローカーはクライアントAの`Session State`を300秒間維持するようになる。

2. クライアントAは`/hello/world`というトピックを`Subscribe`する。ブローカーは、クライアントAの`Session State`を維持する。この`Session State`には、クライアントAが`Subscribe`しているトピック（`/hello/world`）の情報が含まれている。

3. その後、何らかの理由でクライアントAとブローカー間の接続が切断されたとする。この時点から、ブローカーはクライアントAの`Session State`を300秒間維持し続ける。

4. 接続が切断されている間に、別のクライアントであるクライアントBが`/hello/world`宛てのメッセージを`Publish`したとする。ブローカーは、クライアントAの`Session State`を維持しているため、このメッセージを破棄せずに保持する。

5. 300秒が経過する前にクライアントAがMQTTブローカーに再接続すると、ブローカーは維持していたクライアントAの`Session State`を再利用する。これにより、クライアントAは以前に`Subscribe`していたトピック（`/hello/world`）を再度`Subscribe`する必要がなくなる。また、ブローカーが保持していたメッセージ（クライアントBが`Publish`したメッセージ）がクライアントAに配信される。

このように、`Session Expiry Interval`を設定することで、一時的な接続の切断があっても、クライアントとブローカー間の`Session State`が維持され、メッセージの損失を防ぐことができる。

# 参考
- [MQTT Version 3.1.1](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html)
- [MQTT Version 5.0](https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html)
- [docs.aws.amazon.com/ja\_jp/iot/](https://docs.aws.amazon.com/ja_jp/iot/)
任意の写真や動画を3Dで公開する無料のAIツールをオープンソース化しました[Next.js / DepthAnything / Three.js]

<a href="https://www.3dany.com" target="_blank">3DAny</a>は、写真やビデオを立体的な3Dビジュアルに変換する超クールなツールです。想像してみてください。普通の写真やビデオが、私たちのAI技術を使って深みがあり、立体感のある3D作品に変わるんです。それも、早くて簡単に。このツールは、デザイナーやビデオプロデューサー、マーケティング担当者、そして3Dコンテンツ制作に興味がある個人や企業にとって、効率的で使いやすい解決策を提供します。

私たちはユーザーのプライバシーを非常に重視しており、すべての画像やビデオの処理はユーザーのローカルデバイス上で行われ、サーバーにアップロードされることはありません。このローカルAIモデルにより、ユーザーに最高レベルのセキュリティとプライバシー保護を提供します.
本当のガバメントクラウド基礎～利用方式と登場人物たち～

# 内容
社内でAWSの超基礎ともう一つ、ガバメントクラウドの基礎の動画を作成して欲しいとリクエストあり。その内容を資料化したものです。

https://qiita.com/infra365/items/84c41c250b0abcccc70b


# ガバメントクラウドとは
デジタル庁が提供する政府共通クラウド基盤です。標準化対象20業務の移行先としても利用されます。デジタル庁から認定されたクラウドサービスプロバイダー（CSP）の環境が使用されます。今回は自治体がガバメントクラウドを利用する話をします。

![スライド3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/2de69c27-568e-52a1-84a9-94db939fa683.png)

色々なCSPがありますが、AWSの話をします。

![スライド4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/0f3f3995-1c38-7505-d58a-6721eacc3d75.png)

# 共通基盤を利用することのメリット

AWSのアカウントは当然個人でも調達可能です。AWSのサイトに行って必要な情報を入力すればすぐにアカウントは作成できます。

![スライド5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/0e64c465-348f-5d0e-ea64-d14d6fff0aa6.png)

そんな中で個人で別々にアカウントを調達するのではなく共通基盤を利用することのメリットは下記になります。

* 統制
ガバメントクラウドではデジタル庁のアカウントが親アカウントになっていいて、システム利用者はデジタル庁から払い出された子アカウントを使用します。階層構造になっていることで親アカウントから子アカウントに対して色々ポリシー（制限）をかけることが可能なので、統制に役立ちます。

* セキュリティ
子アカウントのログやアラートを親アカウントに送って、セキュリティ情報を集約出来ます。また子アカウントにデジタル庁から提供されるセキュリティのテンプレートを適用することになっているのですが、共通のセキュリティテンプレートを適用することによって一定のセキュリティ水準を担保することが出来ます。

* コスト
大量仕入れによるコストメリットがあります。

![スライド7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/4f72e0d3-9d89-4d5c-55fa-d8cc9bee0ad0.png)

# 利用方式

そんな中で、払い出された子アカウントの中にシステムを構築します。この段階でシステムを利用する自治体の方とシステムを構築保守するASP兼運用管理補助者という人がいます。

![スライド8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/9356469d-6684-2385-0364-b7dd997cf0d4.png)

そしてシステムの利用方式は単独利用方式と共同利用方式という方法があります。

![スライド9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/7d05169d-9d05-681a-205f-a995e655d78a.png)

単独利用方式は自治体（例ではA市）用に環境が払い出されます。各システムベンダーはこの環境の中にシステムを構築していく方式です。

![スライド10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/2d61f3d8-95c2-423e-3693-d8307d96e0d9.png)

共同利用方式は各ベンダー毎に払い出された環境があります。この環境の中にはA市やB市など色々な自治体の環境があってA市職員は各システムのA市環境に接続してシステムを利用します。このような共同の環境を提供することによって運用面でもコスト面でも効率化が図れるためガバメントクラウドでは共同利用方式が推奨されています。

![スライド11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/01307122-119e-69e0-523e-1f9e0cf95dc1.png)

# 環境をつないでくれる人

共同利用方式や単独利用方式でシステムを構築しましたがこの段階ではA市とシステムはつながっていないため、システムを利用することができません。

![スライド12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/33c7734d-a158-ab1b-a5d2-b837bf1473a6.png)

そこで中間に入ってA市とシステムをつないでくれるネットワーク構築運用補助者という人が登場します。

![スライド13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/b6202895-a9fd-f01a-2625-47e910a7acac.png)

ガバメントクラウドに関わる人は下記の人たちです。

* 自治体職員：システムの利用者
* ネットワーク構築運用補助者：間に入ってネットワーク接続してくれる人
* ASP兼運用管理補助者：システムを構築保守する人

![スライド14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/cacf5d0b-eb70-4a1e-b28e-45ce565b948d.png)

# まとめ

![スライド16.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/660f69b7-6b06-6588-9840-392386a3d169.png)

# 勉強会

定期的にAWSやインフラ基礎の勉強会を開催しています。

https://infra365.connpass.com/event/313272/

# 資料

https://speakerdeck.com/toru_kubota/ben-dang-nogabakuraji-chu
iOSのファイルシステムについて理解する【WIP】

# はじめに
今回画像データを扱うことになり、画像データの保存先をRealmなどのDBではなくファイルシステムの領域へと保存することにしました。
本記事は、iOSのファイルシステムについて理解して設計・開発に役立てること、また将来の自身の振り返りに役立てることを目的にしています。

### 参考文献
File System Basics（Updated: 2018-04-09）
https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html

↑6年前のアーカイブドキュメントですが図もあり分かりやすいため上記資料をベースに記載していきます。

# iOSのファイルシステム
## iOSファイルシステムについて
iOSファイルシステムとは、単独で実行されるアプリを対象としており、ユーザーはファイルシステムへ直接アクセスできない。

## iOS標準ディレクトリ
セキュリティ上の理由により、iOSアプリとファイルシステムのやり取りはアプリのSandox内のディレクトリに制限されている。
アプリインストール時にインストーラーがアプリのSandbox内に複数のコンテナディレクトリを生成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245300/a52eeeb8-13aa-58d0-0800-bb6d0c41f0eb.png)
[Figure 1-1  An iOS app operating within its own sandbox directory](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#:~:text=%E5%9B%B3%201%2D1%C2%A0%C2%A0%E7%8B%AC%E8%87%AA%E3%81%AE%E3%82%B5%E3%83%B3%E3%83%89%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%20%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E5%86%85%E3%81%A7%E5%8B%95%E4%BD%9C%E3%81%99%E3%82%8B%20iOS%20%E3%82%A2%E3%83%97%E3%83%AA)

## iOSアプリで一般的に利用されるディレクトリ
- *AppName.app*
    - アプリのバンドル
    - アプリとすべてのリソースが含まれ、このディレクトリに書き込むことはできない
    - ただし、アプリのバンドルに保存されているリソースの読み取り専用アクセスを取得することは可能
    - このディレクトリはiTunes, iCloudによってバックアップされない
- *Documents/*
    - ユーザーが作成したコンテンツを保存するために使用する
    - このディレクトに保存された内容は、ファイル共有を通じてユーザーが利用できる → **ユーザーに公開する可能性のあるファイルのみ配置する必要がある**
    - このディレクトリはiTunes, iCloudによってバックアップされる
- *Documents/Inbox*
    - このディレクトリを利用して、アプリが外部から開くように要求されたファイルにアクセスする
        - 例）メールアプリの場合、アプリに関連されたメールの添付ファイルをここに保存する
    - このディレクトリはiTunes, iCloudによってバックアップされる
- *Library/*
    - サブディレクトリに*Application Support*、*Caches*、*Frameworks*、*Preferences*などを持つ
        - 詳細は[The Library Directory Stores App-Specific Files](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW1)を参照
    - サブディレクトリを利用（作成？）することでユーザーに公開したくないファイルを利用することができる?（⚠理解が曖昧です）
    - Cachesを除くディレクトリの内容はiTunes, iCloudによってバックアップされる
        - ※バックアップから除外したいファイルがある場合は[URLResourceValuesのisExcludedFromBackup](https://developer.apple.com/documentation/foundation/urlresourcevalues/1780002-isexcludedfrombackup)を利用する
- *tmp/*
    - アプリ起動中に利用する一時ファイルを保存する
    - アプリが起動していないとき、システムによって消去される可能性がある
    - このディレクトリはiTunes, iCloudによってバックアップされない
Ubuntuインストール中にCUIからステルスSSIDのWi−Fiに接続しなければいけなくなった話

# はじめに
Ubuntuのインストールを行っている時に、初期設定を終え「さぁ再起動だ」と意気揚々ログインを試みたところ、IDとパスワードの入力画面に何回も戻されてしまいました。

「ログイン画面ループ　Ubuntu」といったワードで検索をしてみると、nvidiaのドライバ関連で同様の現象に陥っていた人がいました。

「ドライバを更新すればいいのね」
->「最初にWi-Fi設定してないやん」
->「ターミナルから設定する記事見つけた」
->「ステルスSSIDやから一覧に出てこんやん」

こういった流れでステルスSSIDのWi-Fiに接続する必要が出てきました...

## 1. 00-installer-config-wifi.yamlの作成/編集
まず、/etc/netplan/ にカレント・ディレクトリを移します。
```bash
cd /etc/netplan
```

Wi-Fi接続のテスト用のファイルを作成または編集していきます。
```bash
sudo nano 00-installer-config-wifi.yaml
```

```yaml
network:
  version: 2
  wifis:
    [ネットワークインターフェースの名前]:
      access-points:
        "[Wi-Fiのネットワーク名]":
        hidden: true
        password: "[Wi-Fiのパスワード]"
      dhcp4: true
      optional: true
```
今回はステルスSSIDに接続するので、`hidden: true`としましょう。
`optional`も`true`にしました。

ネットワークインターフェースの名前はあとから変更できるので、分からなければ一旦`wlp5s0`など任意のものを使用しましょう。

## 2. 接続テスト
接続を確認、設定ファイル作成、実行
```bash
// 接続テスト
sudo netplan --debug try
// 設定ファイル作成
sudo netplan --debug generate
// 実行
sudo netplan apply
```

## 3. deviceの状態確認
```bash
nmcli d status
> DEVICE         TYPE         STATE                            CONNECTION
> [DEVICE_NAME]    wifi         connection(need authentication)  ---
```
上記のように表示されていればOK
以下、`DEVICE_NAME`と書いている箇所は上記で表示されるものを使用します。

## 4. 接続プロファイルを編集
以下のコマンドでインタラクティブに設定を行うことができます。
```bash
sudo nmcli connection edit DEVICE_NAME
```

設定を行っていきましょう
```bash
set ipv4.method auto
set ipv6.method auto
set 802-1x.eap peap
set 802-1x.phase2-auth mschapv2
set 802-1x.identity [接続したいWi-FiのUSERNAME]
set 802-1x.password [接続したいWi-FiのPASSWORD]
set 802-11-wireless-security.keymgmt wpa.eap

// 保存
save
activate
quit
```

activateコマンドを実行すると、ネットワークインターフェースの名前が異なるといったメッセージが出る場合は以下を実行

```bash
sudo nano /etc/NetworkManager/system-connections/DEVICE_NAME.nmconnection
```

connectionの項目を編集しましょう

```
[connection]
interface=INTERFACE_NAME   <= activateコマンド実行時に表示されたネットワークインターフェースの名前に変更
```

ファイル保存後、NetworkManagerを再起動

```bash
systemctl restart NetworkManager
nmcli connection down [DEVICE_NAME]
nmcli connection up [DEVICE_NAME]
```

## 5. deviceの状態確認
```bash
nmcli d status
```
上記コマンドを実行し、STATEがconnectedになっていればWi-Fi接続ができている

## 最後に
ここまでやって、ドライバの更新ができるようになったので解決という風に考えました。
ドライバを更新して、ログインループが解決したので改めてちゃんとWi-Fiの設定をやり直しました。

自分の環境だけかもしれませんが、小さすぎる文字とにらめっこしながらの作業で大変でした。もう二度とやりたくないです。
ステルスSSIDは非推奨らしいと知ったのでやめるべきですね。

記事の内容について、間違いやもっと簡単な方法などありましたら、コメントいただけますとありがたいです。


#### 参考
- [［小ネタ］Ubuntu での Wi-Fi 設定こと始め（ターミナルで設定）](https://ineters.com/unix/ubuntu-wi-fi/)
- [nmcliでwifiに接続する](https://soblin.github.io/techblog/posts/007-nmcli-wifi/)
- [CentOS7でステルスSSIDへ接続する方法](https://qiita.com/n7aka/items/64e8fdd11e3f7ceaa49c)
SESのいいとこ、わるいとこ

これはSESで働くエンジニアさんにも今ご自身の立ち位置や今後のキャリアを考えるための１つの材料として考えてほしいので今はSES会社の管理職の元エンジニア目線でぶっちゃけ、SESの今後の展望も踏まえ書いていきます。

## そもそもSESとは
弊社にご応募いただいたエンジニアさんな中でも、
主に自社サービスなどを扱うベンチャー出身の方なんかはSESと携わったことのない方もいらっしゃいます。

そもそも弊社がSES企業として認識されていなかったり、SESて何？といったベテランのエンジニアさんもご応募いただいております。

SES業界ではいたらいている方々にとっては当たり前のことでも、SESと携わってこなかったIT業界の方もたくさんいらっしゃいます。

私もその一人で今の会社に入るまでSESて言葉は聞くが何？と思っていました。
今いる会社も初めはSESだと知らず内定通知書を見て初めて知った次第です。

端的に表すとエンジニア専門の派遣ですよね。
契約などは派遣だけでなく準委託などもあり複雑ですが、一般の方にわかりやすく一言で表すならこれです。

そんな企業が首都圏だけで一万社以上あるというのですから、まさに群雄割拠。
大小さまざまありますが強い特色・力のある企業だけが生き残れるまさに戦場ですね。

## SESのいいところ
とはいえ働き方次第でSESはいいところもたくさんあります。
- 自分が身につけたいスキルを習得し実務に生かせる
- 経歴とタイミング次第では自分が理想とする案件に参画できる
- 自分の都合で案件を抜けることもできる
- リモート案件もまだまだ多い
- プロフェッショナルを目指すならいい環境
- 現場では意外と自分の意見が通りやすい
- 転職が簡単

## SESのわるいところ
- 同じ作業をしていても所属会社で給与が全然違う
- 場合によってはスキルチェンジを勧められる
- 若手のスキルが伸びずらい
- 同じような毛色の経歴が並ぶのでキャリアアップがスムーズにいかない
- 現場の指示と会社の指示、慣れないとどこに帰属しているのかわからなくなりがち
- ロースキルエンジニアにとってはキャリアアップを目指すには厳しい環境
- 一度SESに浸かるとキャリアを積むまでは抜けだしにくい

といった具合にそれぞれのいいとこ悪いとこがあるのでエンジニアの皆さんは今後どのようなエンジニアとしてのキャリアと積んでいきたいか。将来どんなエンジニアになりたいかをしっかり考えて、最大限メリットを生かせる働き方をお勧めします。

この記事ではいいとこわるいとこを羅列しましたが次回以降はそれぞれを掘り下げてお話ししたいと思います。


ご拝読ありがとうございます。


2024/5/10　「[SESのいいとこ、わるいとこ（いいとこ編）](https://qiita.com/bss_nagasawa/items/0403afd514c66fd6eb55)」を公開いたしました。
あわせて読んでいただければ幸いです。

2024/5/15「SESのいいとこ、わるいとこ（わるいとこ編）(https://qiita.com/bss_nagasawa/items/f63b8ed3c3d109738e9c)」を公開いたしました。
あわせて読んでいただければ幸いです。


【PR】
弊社の採用ページもぜひあわせてご覧下さい。
https://recruit.bss-j.co.jp/