OmniAICreator/Qiita-1.07M huggingface dataset:
Flutterのチュートリアルを学んでみた(1)

# はじめてのFlutter！スマホアプリ作りへの第一歩 🚀

こんにちは！
今回はFlutterのチュートリアルをじっくり勉強していきたいと思います。

## Flutterってなにかな？ 🤔

Flutterは、私たちが大好きなスマホアプリを作るための魔法の道具箱みたいなものです。
一番すごいところは、iPhoneとAndroidの両方のアプリを一度に作れることです！

## 準備するもの 📝

お料理と同じように、始める前に必要なものを確認しましょう：

### パソコンの条件 🖥
- MacOS（64bitのもの）
- ハードディスクの空き容量が700MB以上

### 必要なツール 🔧
これらは魔法の呪文のように使うツールです：
- bash（コマンドを実行するための道具）
- curl（インターネットからファイルを取得する道具）
- git（プログラムのバージョン管理をする道具）
- mkdir（新しいフォルダを作る道具）
- rm（不要なファイルを削除する道具）
- unzip（圧縮ファイルを解凍する道具）
- which（プログラムの場所を探す道具）

そして一番大切なのは...
- やる気かな（これがあれば何でもできる！笑）

## インストール手順 👨‍💻

### Step 1: Flutterをダウンロードしよう！ 📥

1. まずは[Flutter公式サイト](https://flutter.io/docs/get-started/install/macos)に行きます
2. 大きなダウンロードボタンをクリック
3. ダウンロードしたファイルは宝箱みたいなもの。解凍（かいとう）して中身を取り出します！

```bash
# フォルダを作って、その中に Flutter を入れよう
cd ~/development
unzip ~/Downloads/flutter_macos_v1.0.0-stable.zip
```

### Step 2: パソコンにFlutterの居場所を教えよう 🏠

パソコンがFlutterを見つけられるように、道しるべを付けます：

```bash
export PATH="$PATH:`pwd`/flutter/bin"
```

これは「ここにFlutterがいるよ！」とパソコンに教えているようなものです。

### Step 3: うまく準備できたか確認しよう 🔍

```bash
flutter --version
```

このコマンドを打って、Flutterが「はい！」と返事をしてくれたら成功です！

## 開発環境のチェック 🚦

Flutterには「ドクター」という便利な機能があります。
まるで健康診断のように、必要なものが全部そろっているかチェックしてくれます：

```bash
flutter doctor
```

### もし足りないものがあったら... 🔧

ドクターが教えてくれた足りないものを一つずつインストールしていきましょう：

1. **Xcodeが必要だよ！** と言われたら
   - App Storeからインストール
   - インストールが終わったら起動して確認

2. **Android Studioが必要だよ！** と言われたら
   - 公式サイトからダウンロード
   - インストールウィザードの案内に従う

## 実際にアプリを動かしてみよう 📱

### iPhoneシミュレータの起動

```bash
open -a Simulator
```

まるで魔法みたい！パソコンの中にiPhoneが現れます。

### Androidエミュレータの設定

1. Android Studioを開く
2. 右上の「AVD Manager」をクリック
3. 「Create Virtual Device」で新しいスマホを作る
4. 好きなスマホの種類を選ぶ

## 困ったときは... 🆘

* Flutter doctorの診断結果をよく読んでみよう
* エラーメッセージは大事なヒントです
* 分からないことはインターネットで調べるか、先生に聞いてみよう！

## おめでとう！ 🎉

ここまでできたら、もうアプリ作りへの準備は整いました！
次は実際にアプリを作っていきましょう。

## 大切なポイント ⭐️

1. 焦らず一歩ずつ進もう
2. エラーは友達！たくさん出会って、たくさん学ぼう
3. 困ったら戻って確認。急がば回れ！

## 次は何をする？ 🎯

チュートリアルをみます。


## 参考にしたサイト 📚

この説明は以下のサイトを参考に作成しました：
- [Flutter 導入](https://flutter.ctrnost.com/install/)
  - とても分かりやすく解説されているので、もっと詳しく知りたい人はチェックしてみてください！
- [Flutter 公式サイト](https://flutter.dev/docs/get-started/install)
  - 最新の情報はここでチェックできます！

みなさんも、分からないことがあったらこれらのサイトを参考にしてみてください。
困ったときの道しるべになってくれますよ！
||= とは

# どちらの値もfalsedであれば代入される
```rb
limit ||= 10
```
>このコードの意味は「変数limitがnilまたはfalseであれば、10を代入する(それ以外はlimitの値をそのまま使う)」の意味になります。

### `||=`は短縮形
>`n += 1`が`n=n+1`と展開できるように、limit ||=10を次のように展開すると次のように展開すると意味が分かりやすくなります。
```rb
limit = limit || 10
```
```rb
irb(main):001> limit = nil
=> nil
irb(main):002> limit ||= 10
=> 10
irb(main):003> limit
=> 10
irb(main):004> limit ||= 20
=> 10
irb(main):005> limit
=> 10
```
>limitが真（つまりfalseでもnilでもない値)であれば、limit = limit隣、代入を実行しても特に何も変わりません。一方、limitが偽（つまりfalseまたはnil)であれば、Rubyは||の右辺である10を評価します。

>`X ||= A`というコードを見たら「変数Xがnilまたはfalseなら、AをXに代入」と頭の中で読み替えるようにしください。

### `||`とは
>条件１||条件２は「条件１または条件２」の意味で、条件１か条件２のいずれかが真であれば真になります
```rb
irb(main):011> t1 = true
=> true
irb(main):012> f1 = false
=> false
irb(main):013> f2 = false
=> false
irb(main):014> t1 || f1
=> true
irb(main):015> f1 || f2
=> false
```

https://gihyo.jp/book/2017/978-4-7741-9397-7
ABC383Aをjavascriptで解いた

# [今日の問題](https://atcoder.jp/contests/abc383/tasks/abc383_a)
↑押してください。
# 自分の回答(javascript)
```javascript
function Main(input){
    min = 1e18
    max = -1e18
    let abc = "abcdefghijklmnopqrstuvwxyz".split("")
    let ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
    let f = 2
    if(f == 0){
      input = parseInt(input.trim())
    }
    if(f == 1){
      input = input.trim().split("\n").map((a)=>parseInt(a))
    }
    if(f == 2){
      input = input.trim().split("\n").map((a)=>a.split(" ").map((b)=>parseInt(b)))
    }
    //ここより上は定型文です。
   let n = input.shift()[0]
   now = 0
   count = 0
   for(let i = 1;i<=input[n-1][0];i++){
     if(i == input[count][0]){
       now += input[count][1]
       count ++
     }
     if(now > 0&&i != input[n-1][0]){
     now --
     }
   }
   console.log(now)
  }
  Main(require("fs").readFileSync(0, "utf8"));
  

```
# 工夫した点
加湿器がからになる場合を注意しなければいけません。時系列順に進めてときます。
028 AI屋さんの　LLMにトークン全文入力　TOEIC+streamlit＋cloudrun＋Gemini


028 AI屋さんの　LLMにトークン全文入力　TOEIC+streamlit＋cloudrun＋Gemini


折角なので、何かアプリをサクッと実装してみましょう。
英語の先生もしてくれる
webアプリを　クラウドデプロイしておきます。
冬休みの宿題にお試しください。


TOEIC本の例文を全文入力版は、支障がありそうなので　そちらは
非公開ですが、
事前学習済みの内容でも、十分ボリューミーです。

　１、TOEIC特化英会話教師　geminiちゃん
　２、また、訪日外国人向け神社仏閣推しの観光案内英会話教師版や
　３、思考強化型　英会話教師版もあります。
 
思考強化型は考えが外部にダダ漏れで　見ていて楽しいです。
こっちをチャットにすると　文字多すぎでした。
訪日外国人向けの観光案内向けも、特定の地域の観光資源を全文入力すると良いかと思います。





![スクリーンショット 2024-12-25 14.56.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/b830ff88-a2b2-0228-bf7c-c9052a439f2e.png)





お試しはこちらから


https://st02.bono0.com/toeic012


キャラ設定済みの思考強化LLMの
英語の先生に無茶振りすると　めっちゃ考えてくれています。


![スクリーンショット 2024-12-25 15.30.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/579fa19b-61e0-7697-d323-96e41803644e.png)





https://ai.google.dev/gemini-api/docs/thinking-mode?hl=ja




目次

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

今回も、無事に英会話webアプリをデプロイできました。

　028 AI屋さんの　LLMにトークン全文入力　TOEIC+streamlit＋cloudrun＋Gemini

完成です。おめでとうございます。


ー続くー
投資複利計算ツールを作ってみた

*とりあえずChatgptに日本語を直してもらった
### 投資複利計算ツールを作ってみた

こんにちは！日本でエンジニアとして働いている社会人3年目の中国人、葉子です。
今回は、自作した投資複利計算ツールについてご紹介します。

### プロジェクト概要

今年、新しいNISA制度をきっかけに、私自身も投資の勉強を始めることにしました。そして、投資や貯蓄の計画を立てる上で重要な複利計算を簡単に行えるツールを作成しました。このツールは、ユーザーが複利計算を手軽に行い、その結果を視覚的に確認できるように設計されています。

**URL**: [複利計算ツール](https://compond-interest.vercel.app/)

### 使用技術

- **フロントエンド**: React, Next.js
    - ユーザーインターフェースの構築にNext.jsを採用し、シンプルかつ高速な動作を実現しました。（自分の仕事では主にシンプルなReactを使っていますが、Next.jsはフロントエンドからバックエンドまで対応できるので、次の個人開発ではNext.jsだけを使う予定です。）
- **バックエンド**: Python (FastAPI)
    - 計算ロジックは仲間が作成したもので、それを基にAPI処理をFastAPIで実装しました。
- **デプロイ**: Vercel (フロントエンド), Render (バックエンド)
    - フロントエンドとバックエンドをそれぞれ適切なプラットフォームにデプロイ。
    - 計算にnumpyとpandasを使用した結果、VercelのServerless Functionのメモリがオーバーしたため、バックエンドはRenderにデプロイしました。
    - Renderは無料プランを利用しているので、GitHub Actionsを使い、定期的にRenderのサーバーを呼び出しています。

### 主な機能

1. **複利計算**: 初期投資金額、利率、投資期間などを入力することで、複利の増加額を計算します。
2. **結果の視覚化**: 計算結果をグラフで表示し、視覚的に理解しやすくしています。
3. **ユーザーフレンドリーなUI**: シンプルで直感的に操作できるデザインを心がけました。

### プロジェクトのポイント

- **フロントエンドとバックエンドの分離設計**
フロントエンドとバックエンドを明確に分離することで、保守性を高めました。
- **レスポンシブデザイン**
モバイルとデスクトップの両方で快適に利用できるよう、レスポンシブデザインを採用しています。
- **APIによる効率的なデータ処理**
入力データはバックエンドに送信され、計算処理を行った後、結果を返します。これにより、フロントエンド側の負荷を軽減しています。
- **多言語対応**
今は日本語、中国語、英語を対応しています

### 課題と今後の改善点

- **エラーハンドリングの強化**
入力データのバリデーションや、APIエラー発生時の処理をさらに強化したいと考えています。
- **投資シミュレーションの追加機能**
現在の機能に加え、取り崩し機能を追加予定です。

### 最後に

このプロジェクトを通じて、フロントエンドとバックエンドの統合やデプロイについて深く学ぶことができました。ぜひ使ってみていただき、ご意見やフィードバックをいただけると嬉しいです！
Genie教育のためにやったことあれこれ

# 前書き
（Qiita初投稿です！！）

DatabricksでGenieがリリースされた直後から使用させていただく機会が多く、データやSQLに精通していない方が使うことを前提にチューニングを行なっていたため、生成精度を向上するノウハウがかなり蓄積されておりました。
培ったものを記事にして世に出そうと画策しておりましたが後回しにしてしまい結局この時期に…<a href="https://qiita.com/advent-calendar/2024/databricks" target="blank">Databricks Advent Calendar 2024</a>に乗っかってGenieの精度を上げるのに役立ったことを書いておきたいと思います。

# Genieを教育しない場合について
当初は手を加えずにそのまま使う、というのはなかなか難しかったように思います（特にエンジニア以外の方にとっては）。
厳しいポイントとしてはクエリするテーブルの選択を誤ったり、英語で返答が来る、といったことが挙げられます。Databricksはものすごい速さでアップデートがはいっているため、現在は改善されているかもしれませんが…
当時はそのまま使うには多少なりとも精度に不安があったため、私はGenieの教育担当として色々試してみる必要があったのでした。

# 精度向上に役立ったこと
## General Instructions
システムプロンプト的役割のGeneral Instructionsですが、私はここを充実させることに最も時間と手間を割きました。
結果的に100行近くのプロンプトを書いていました。
必要に応じて継ぎ足しを繰り返したところ膨れ上がってしまったようです。

指示としては下記のような内容を詳しめに記述していました。
- 回答は全て日本語で出力するように指示(フロントが使う想定で作り込んでいたため、集計結果列名まで日本語で出力させるように強く言い聞かせました)
```プロンプト例
* 回答は全て日本語で出力してください
* あなたが質問に回答する際に用いるテーブルの列名は全て日本語で名付けをして表示してください。このGenieワークスペースのユーザーは英語を理解できません。日本語でリネームを行うとき、jan_code AS `JANコード`のように、バッククォートで囲んでください。
```
↑もう少し適切な表現があるように思いますが、列名を日本語にリネームさせるのが本当に難しく、うまくいった上記プロンプトのまま現在まで放置されています。

- 売上比較を行う時に使用する列の指定（販売数量なのか金額なのか）
- 社内用語とそれに対応するロジックの説明
- 共通ロジック（集計期間指定方法など）

↑プロンプトを詳しく記載することは控えますが、生成してほしいSQLの例を交えて記載しています。

また、割合の算出は"%"で,売上金額など大きい数字を出す場合は","区切りにしてほしいとのオーダーを受けたため、その制御もシステムプロンプトで行いました。

```プロンプト例
* 売上金額など、数値を表示する場合は、処理の最後で3桁ごとにカンマ区切りに整形してください。処理の例としてはFORMAT_NUMBER(sales_quantity,0)のようになります。
* 割合や百分率を扱う場合は小数点第二位までで末尾が'%'となるような表記にフォーマットを統一してください。
```

しかし、集計結果の見やすさ重視で集計結果テーブルのINTをSTRINGに変更することでオートビジュアライゼーション機能を使用したビジュアル化することができなくなるためあまりおすすめはしません。
![スクリーンショット 2024-12-25 15.22.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3874294/5ee5bf7d-75b1-db63-25be-f810662caba2.png)


質問して、生成された結果を見てシステムプロンプトの修正・拡充を行うというプロセスをひたすら繰り返しました。
回答の精度が安定した要因のほとんどはGeneral Instructionsの内容を充実させたことにあると思うくらいにはGenieへの影響が大きい項目です。

## サンプルクエリー
次に時間をかけたことはサンプルクエリーの充実です。

詳しいクエリー例を書くことは避けますが、よく集計する内容や生成がむずかしそうな質問、想定とは異なるSQLが生成された質問をサンプルクエリーに登録しました。

実際にGenieに送る質問と、サンプルクエリーに入力する質問が完全に一致していなくても、ニュアンスが似ていたらクエリー例を参考にSQLを書いてくれている印象がありました。
繰り返し投げられる質問がある場合には非常に有効なチューニング方法であると言えるでしょう。

## テーブルキャプション
こちらは直接Genieに関係のある機能ではありませんが、マネージドテーブルのカラムごとに設定できるキャプションの充実も行いました。

カラムの論理名やカラムの内容、意味、集計に使用する・しないについて日本語で記入しました。

いくつか例を挙げると下記のようなイメージです。
- 値として、"0","1","2"が入る顧客情報テーブルのgenderカラムの場合
`性別を表すカラム。0:不明 1:男性 2:女性`
- レコードの更新日を表すupdate_atカラムの場合
`レコードの更新日を表す。監査列のため基本的に集計に使用することはない。`
→本当に集計に使用するタイムスタンプカラムには集計に使用する旨記入しておきます。

結果、かなり効果がありました。
私の場合、性別カラムを正しく扱わせることはシステムプロンプトをこねこねしても達成できておりませんでしたがキャプションを整備したら解決しました。
自動でキャプション情報を解釈してクエリー生成に活用してくれるGenieは天才だと思います。
キャプションとして保存した内容は各テーブルのメタデータファイルに入るんですかね🤔

## フィードバック
回答を生成した後にでるgoodボタン、badボタンです。
Genieと触れ合っている中で、彼がこのフィードバックに強い影響を受けているのではないかと思うようになりました。
特に悪いフィードバックを行うと、即座に悪いフィードバックを受けたのと似た内容の生成を避けるようになった印象があります。
Genieはよくユーザーとの対話を通じて学習するAIだよ〜という話がされていると思いますが、本当にそうなんだなぁと実感しています。

# あとがき
Genieの精度向上に役立ったのは、用意されていた機能のほぼ全部でした〜というような内容になってしまいました。
他のLLMを教育するよりはるかに簡単にチューニングを行うことができることが魅力だなと改めて感じました！
今後も使い倒していこうと思います！
声が変われば人生も変わるという説

# 誰かに何かを伝える際に何を重要としているか？

ここで一つ質問です。
貴方は誰かに何かを伝える場合に何を重要視して話をしていますか？
多くの方は「内容」と答えるかと思います。

しかし、内容以前の重要な項目を見落としがちです。

それが「声」です。

# 人の第一印象の内、声が占める割合はおよそ４割

心理学では視覚55%、聴覚38%、言語7%とされている模様。
※詳細は「メラビアンの法則」等でググってください。

昨今、リモートワークの普及などもあり特にカメラをOFFにして会話をしているシーンでは、
視覚情報が閉ざされているので声が第一印象に影響する割合は更に高くなるものと予想されます。

# 例えばこんな経験はないだろうか？

- 同じ話なのに人によって納得度が違う
- 同じジョークなのに人によって面白さが違う
- 同じプレゼンなのに人によって説得力が違う

どれも「何を話すか？」よりも「誰が話すか？」が重要という現実を顕著に表している事例かと思います。

# この差は何故生まれるのか？

その秘密は「声」とそこから生まれる「間」にあります。
これらが備わると人は自然と耳を傾けたくなります。

例えば学校の授業は「内容」にフォーカスされている事が多いですが、
概ね、この「声」と「間」の要素が足りていない為、
端的に言えば面白くない授業となりやすいのではないかと。

また、「お互いの関係値や自身のバックボーンにより生み出された声」の持つ説得力からも、こういった差が生まれるものと考えられます。

# 声の要素には個人差がある

これは当然の事であり、

- 素の声の音色が良い
- 一段トーンを上げた際の音色が良い

等、個人により様々です。

勿論、逆も然りで、素の場合も一段トーンを上げた場合も音色がよろしくない場合もあります。
むしろこちらが多数派で、これは仕方のない事と納得する他ありません。

天性の「持てる声の民」と「持たざる声の民」は確かに存在します。

# では「持たざる声の民」はどうするべきか

「持たざる声の民」においても訓練によりその声の音色を磨く事は可能です。

例えば、アナウンサーや歌手、芸人においても幾多の場数や発声練習により、誰かに訴求する為の声を磨き上げています。

我々のようにエンジニアと呼ばれる職業においても、例えばお客様に提案をする機会は多々あるかと思うので、
訓練により後天的に良い声を習得できるのであればそれは身に着けた方が得は大きいと言えます。

# 声が良くなる事の利点

特に前述のオンラインかつカメラをOFFにして会話をしているシーンでは第一印象が劇的に好印象となりやすくなるでしょう。
相手が好印象を持った場合、より話を聴いてくれる、更には協力的にも成り得る可能性は有り得ます。

好き・嫌いという部分の原動力は思った以上に大きいもので仮に悪印象に近い感触だった場合は、
内容が100点だったとしても訴求力の部分で今一つな反応を見せることは多々あることでしょう。

更に言えば、

- 第一印象が悪印象の場合は内容は100点以外は許されない、または100点でも許されない。
- 第一印象が好印象の場合は内容が80点でも残りの20点を埋めるべく、より建設的に、より協力的な姿勢を見せてくれることは有り得る。

内容が今一つでもある種、惚れさせていれば、割と話は聞いてくれたりするというのは、
仕事においても友人間や男女間のコミュニケーションにおいてもよくある話ではあります。

つまりは「良い声」は「信頼関係」を築く上で大きな武器となるでしょう。

# 声が変わればどのように人が変わるのか？

「良い声」という武器を手に「信頼関係」をより築くことが出来たならば、
それは貴方自身の大きな糧となり、また一つ一つが「成功体験」にもなるでしょう。

「成功体験」が積み重なっていった結果、それは「自己肯定感」にも繋がるでしょう。

そして「自己肯定感」は主体性や前向きな思考、チャレンジ精神に繋がります。

# 声の持つ力を信じろ！

いかがでしょう？
こうして考えてみると声を良くするというある種の小さな行動が、
大きなターニングポイントに成り得る気がしてきませんか？

人が変われば新しい可能性が生まれ、そして人生をも大きく変えてゆく事でしょう。

今からでも遅くはありません、声のトレーニングを始めてみませんか？
貴方の素敵な声でいずれ世界を魅了して頂ければと思います。
Microsoft Fabric Warehouse の TRUNCATE と DELETE の違いの確認

## はじめに

最近？ Fabric Warehoues で TRUNCATE がサポートされたようですが、Delta Lake は TRUNCATEコマンドはサポートされていないため、DELETEは何が違うのか気になったので確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/05a4e36f-3fa1-1296-d7e1-c09681acfb43.png)
引用：https://learn.microsoft.com/ja-jp/fabric/data-warehouse/tsql-surface-area

:::note info

SQL Server ではTRUNCATEは各行のDELETE をトランザクションログに記録せずに、データファイルをパージして処理するというメタデータ操作的な作業であるため、高速にデータ削除が可能というものでした

参考：https://learn.microsoft.com/ja-jp/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-ver16

:::

## 準備 

以下のテーブルで検証します。

```sql:sql

CREATE TABLE [dbo].[Date] (

	[DateID] int NOT NULL, 
	[Date] datetime2(6) NULL, 
	[DateBKey] char(10) NULL, 
	[DayOfMonth] varchar(2) NULL, 
	[DaySuffix] varchar(4) NULL, 
	[DayName] varchar(9) NULL, 
	[DayOfWeek] char(1) NULL, 
	[DayOfWeekInMonth] varchar(2) NULL, 
	[DayOfWeekInYear] varchar(2) NULL, 
	[DayOfQuarter] varchar(3) NULL, 
	[DayOfYear] varchar(3) NULL, 
	[WeekOfMonth] varchar(1) NULL, 
	[WeekOfQuarter] varchar(2) NULL, 
	[WeekOfYear] varchar(2) NULL, 
	[Month] varchar(2) NULL, 
	[MonthName] varchar(9) NULL, 
	[MonthOfQuarter] varchar(2) NULL, 
	[Quarter] char(1) NULL, 
	[QuarterName] varchar(9) NULL, 
	[Year] char(4) NULL, 
	[YearName] char(7) NULL, 
	[MonthYear] char(10) NULL, 
	[MMYYYY] char(6) NULL, 
	[FirstDayOfMonth] date NULL, 
	[LastDayOfMonth] date NULL, 
	[FirstDayOfQuarter] date NULL, 
	[LastDayOfQuarter] date NULL, 
	[FirstDayOfYear] date NULL, 
	[LastDayOfYear] date NULL, 
	[IsHolidayUSA] bit NULL, 
	[IsWeekday] bit NULL, 
	[HolidayUSA] varchar(50) NULL
);


```


## 検証 1. 全件DELETE 

1. データ投入後、DELETE してみます。

    ```sql:sql
    
    DELETE
    FROM [sandWH].[dbo].[Date];
    
    ```


1.  OneLake File Explorer から delta_logの確認。左がデータ投入のログ、右がDELETE です。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/93daa2fe-fd51-67a1-fc9d-b4ba53dc5e0a.png)

DELETE は Deleta Lake の仕様通りParquet を参照先から外していることがわかります。なお、二回目以降の DELETE では テーブルプロトコルの情報は出てきませんでした。

## 検証 2. TRUNCATE


1. データ投入後、DELETE してみます。

    ```sql:sql
    
    TRUNCATE TABLE [sandWH].[dbo].[Date];
    
    ```


1.  OneLake File Explorer から delta_logの確認。左がデータ投入のログ、右がTRUNCATE です。    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f8da2d5b-4222-afee-feef-db6d909331e4.png)

    DELETEのときと同じようなファイル remove ログが記録されています。

## 検証 3. DELETE WHERE


1. データ投入後、DELETE してみます。

    ```sql:sql
    
    DELETE
    FROM [sandWH].[dbo].[Date] where [DateID] = 20150317;
    
    ```


1.  OneLake File Explorer から delta_logの確認。左がデータ投入のログ、右がDELETE です。全件の削除ではないので、新しいバージョンの parquet ファイルが add されています。
        
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/f5bc4ae4-57bb-adeb-aaae-d32b24215cca.png)


やはりTRUNCATE と DELETE は少なくともdelta_log からは同じ操作扱いであることがわかりました。
ABC382Dをjavascriptで解いた

# [今日の問題](https://atcoder.jp/contests/abc382/tasks/abc382_d)
↑押してください。
# 自分の回答(javascript)
```javascript
function Main(input){
    min = 1e18
    max = -1e18
    let abc = "abcdefghijklmnopqrstuvwxyz".split("")
    let ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
    let f = 1
    if(f == 0){
      input = parseInt(input.trim())
    }
    if(f == 1){
      input = input.trim().split(" ").map((a)=>parseInt(a))
    }
    if(f == 2){
      input = input.trim().split("\n").map((a)=>a.split(" ").map((b)=>parseInt(b)))
    }
    //ここより上は定型文です。
   let [n,m] = input
   res = []
   for(let i = 1;i<11;i++){
     dfs(i,1,[i])
   }
   
   console.log(res.length)
   console.log(res.join("\n"))
   function dfs(a,depth,list){
     for(let i = 0;i<11;i++){
       list.push(a+10+i)
       
       //console.log(list.join(" "))
       if(((m-(a+10+i))/10)>=n-(depth+1)||((depth+1) == n&&m>=(a+10+i))){
         if(depth+1 == n){
           res.push(list.join(" "))
         }else{
          dfs(a+10+i,depth+1,list)
         }
       }
       list.pop()
     }
   }
  }
  Main(require("fs").readFileSync(0, "utf8"));
  

```
# 工夫した点
dfsによる全探索です。途中でありえない可能性は排除することによって、高速化し時間に間に合うようしています。D問題にしては簡単めかもしれないです。
ABC382Cをjavascriptで解いた

# [今日の問題](https://atcoder.jp/contests/abc382/tasks/abc382_c)
↑押してください。
# 自分の回答(javascript)
```javascript
function Main(input){
    min = 1e18
    max = -1e18
    let abc = "abcdefghijklmnopqrstuvwxyz".split("")
    let ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
    let f = 2
    if(f == 0){
      input = parseInt(input.trim())
    }
    if(f == 1){
      input = input.trim().split("\n").map((a)=>parseInt(a))
    }
    if(f == 2){
      input = input.trim().split("\n").map((a)=>a.split(" ").map((b)=>parseInt(b)))
    }
    //ここより上は定型文です。
   let [n,m] = input.shift()
   let alist = input.shift()
   let blist = input.shift()
   let junbi = new Array(200002).fill(-1)
   count = 0
   for(let i = 200001;i>=0;i--){
     while(alist[count]>i&&count != -2){
       
       count ++
       if(count>=n){
         count = -2
         break
       }
     }
     junbi[i] = count
   }
   res = []
   for(let i = 0;i<m;i++){
     res.push(junbi[blist[i]]+1)
   }
   console.log(res.join(" "))
   
   //console.log(junbi)
  }
  Main(require("fs").readFileSync(0, "utf8"));
  

```
# 工夫した点
あらかじめ表を作っておくことによって高速に求められます。美味しさが大きければ大きいほど、届く客はどんどん奥になっていくことを利用します。
今年の総括と来年以降に向けて（2024年度編）

# はじめに

この記事は、Qiita Advent Calendar 25日目の記事です。
以下の記事より、すべての記事をご覧になれます。

https://qiita.com/0_terarin_0/items/2b60d47a2d0e64a273c3

# 本編

## 今年頑張ったこと

### ①仮想化

今年は全体的に仮想化について学ぶ機会が多かったと考えています。具体的には、UTMやVMware Fusionなどを使用する機会が例年に比べて多かったと思います。それから、Asahi Linuxのデュアルブートを行ったのも今年僕が頑張った中では大きかった気がしますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/debfdc43-1049-f598-af9a-4e8763de5038.png)

![screenshot-2024-12-25-04-44-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583428/f01f9156-be99-a60b-9ae5-d45855f0fe00.png)

### ②VPN

Softetherの使ったVPNの構築、それからもちろんTailscaleも含め、結構色々なVPNを今年は構築したような気がします。

https://ja.softether.org/

https://tailscale.com/

来年は、もっと拠点間VPNとかにも力を入れていきたいと思っています。

### まとめ

今年は全体的に自分自身の自由な時間があまりなくて新しい技術というものに触れる時が少なかったと思います。来年は、基礎から順番にもう一度幅広く色々な分野を知って行きたいなって思ったりしています。

## 来年頑張っていきたいこと。

### ①データベース関連

自分が今まで触ったことのあるデータベースといえばせいぜいFirestoreぐらいです。

https://firebase.google.com/docs/firestore?hl=ja

めちゃめちゃ便利なサービスなのですが、やっぱり世の中の大半はSQLが中心だと思っています。来年は、SQLをはじめとしたデータベースの基本から学習していきたいと考えています。

### ②Rust

今年いろいろなアプリを試して思ったことは、Rustの凄さです。Rustって結構色々なところで使われていますけど、まあとにかく速度が早くてかつ色々なところで使える。こんなにRustの便利さを享受しておきながらRustを知っておきながら理解してないとかはあるまじきなので、来年は何か一つアプリを作っていきたいと思います。

https://www.rust-lang.org/ja

ちなみに僕が紹介したRust関連のソフトは下のものになります。

https://alacritty.org/

https://zed.dev/

### ③Linux関連をより深く

今年は様々なアーキテクチャやディストリビューションのLinuxに触れてきました。来年は、もっと組み込みの方を中心にもっとLinuxを学習していきたいと思っています。

https://fedoraproject.org/ja/

https://openwrt.org/

https://www.debian.org/

### ④C関連

全然学習していなかったC関連ですが、色々なアプリをビルドしていくうちにやっぱ学習する必要があるなと改めて痛感。こちらもぼちぼち学習していきたいと思います。

# 最後に

これで今年もアドカレ完走賞です！来年はもっといろいろな記事を書けるようにさらに学習を進めていきたいと思います。それでは皆さん、良いお年を〜！
Figmaを導入してから、社内にFigma仲間が増えるまでの歩み

みなさんこんにちは！Fusicアドベントカレンダー24日目の投稿です。（1日遅れてしまいました…猛省）
最近、社内でFigmaのより良い使い方を習得したいと言ってくれる人が増えて来たので、鉄は熱いうちに打て！ということで勉強会やハンズオンを短期間で複数回行いました。
「Figmaとは何か」をプロジェクトメンバーに説明して回っていた頃から比べると、社内認知度も上がったな〜嬉しいな〜とふと感じたので、社内ツールとして導入してからみんなが使うようになるまでの道のりを振り返ってみたいと思います。
（もちろん、私が知らないところでずっと使ってたよ！勢もいると思いますので、あくまでも私目線の振り返りになります！）

これからFigmaを導入して行きたい方などに何かお役立ちできれば幸いです！

### 背景
Fusicは長年、社内にデザイナーはおらず、プロジェクトごとに必要に応じてパートナー企業のデザイナーと協業する形を取っていました。そのため、社内で共通したデザインツールや運用の知見などもなく、それぞれのプロジェクトでエンジニアが独自の知見でデザインを実装に反映していくことが多かった状況でした。

4年ほど前に私を社内の一人目デザイナーとして採用して頂いてから、Figma布教活動の旅が始まります。

### まずは草の根活動
Figmaを公式デザインツールとさせてください！と最初にアナウンスをしても良かったかもしれませんが、下記のような理由から、まずは草の根活動で小さく始めました。

- 普段どのように開発を進めているのかを知って行きながら、よりよくしていく上で本当にFigmaが最適なのか見極めて行きたい（自分目線）
- 私は使いたいけど、みんなは使いにくかったりしないかな？を確かめるために、Figmaの導入が最適なのかを実際のプロジェクトで一緒に考えて行きたい
- デザイナーと密な協業も初めてな中、使用するツールまで強制されてしまうと、新しい要素が多すぎてハードルが上がってしまうのではないかという懸念

というわけで、プロジェクトに参画するたび、開発が始まる前に開発メンバーに対してFigmaの概要・使いづらければ別のツールでも対応可能な旨を伝えてまずはFigmaを導入する、という流れを繰り返しました。

繰り返して行く中で、開発メンバーから拒否反応を感じたり、使いづらいというフィードバックをもらうことはなく、「これめっちゃいいね！」といった反応が多かったです。
（みんな新しいことに対してとても前向きに乗っかってくれて、ポジティブネガティブのフィードバックも真摯にしてくれるので、本当にありがたいし素敵な文化だなと思います！）

### Figmaの全体像を掴むための勉強会
Fusicでは、プロジェクトごとにエンジニア自身が顧客とシステム全体像をすり合わせるためにイメージ図やワイヤーフレームを起こす機会もたくさんあります。

いくつかのプロジェクトでFigmaを導入したくらいの頃から、まだプロジェクトで一緒になったことがないエンジニアからも「最近よく聞くから、お客さんに見せるイメージ図を作るときとかにFigmaを使い始めたんだ〜」という話や、「もともと使ってたんだけど、知りたいことあるんだ〜」という話をちょくちょく聞かせてもらえるようになりました。

さらに話を聞いてみると「なんとなく雰囲気で使い始めたけど、共有の仕方だったり、共同編集の仕方だったり、図を作る以外の操作が分からない」といった感想が多かったので、鉄は熱いうちに！！！ということで勉強会を定期的に開催しました。

内容としては以下のようなものです。

- イメージ図を作るのに必要最低限な基本操作
- チーム・プロジェクト・ファイル・ページなどの概念
- 共有の方法
- 他のデザインツールとの違い
- 現状の開発フローでどんな風に使うとよさそうか
- Professionalプラン以上を使うとできること・幸せになること
- 最後にハンズオンで、プロジェクト開始からイメージ図作成・共有までを通してやってみる、など

20名前後くらい参加してくださるような会もあり、興味を持ってもらえてとても嬉しかったのを覚えています。
開催後には毎回アンケートを行って、分かりづらい説明や他に需要のあるトピックなどを回収してコンテンツに反映していきました。

勉強会に参加してもらったり、その後も使い続けてもらうために工夫したこと↓

- 参加者募集のタイミングで、参加ハードルを極限まで下げる
    - Figma聞いたことある！くらいで全然参加OKです！を伝える
    - 興味あるけど使わないかもしれない、でも全然OKです！を伝える
    - 勉強会中に完全理解する必要は皆無です！あとから気になることどんどん聞いてください！を伝える
    - Figmaを練習するのは、あくまでもやりたいことを達成するために操作で困らないためであって、Figmaを使いこなすことが大事という趣旨ではないよ！自分の手に馴染めば何でもOK！を伝える
    - 勉強会が終わった後も、「その後どうですか？操作に困って手が止まっちゃうことあります？」など雑談しに行く
    - などなど

そしてこの頃くらいから、社内で「Figma良いんじゃない？」という空気が顕在化し始め、上層部の方たちからも「プロジェクトによっては必要に応じてきちんとお金を払って良いプランを使う方が良い！」ということで稟議のフローを作ってくださったりと、Figmaというツールの認知がかなり広まってきた気がします。Figmaがみんなにとって使いやすいものと言えそうという感覚も個人的に得られました。
急に「これ使いたい！」と持ち込んだツールではあるにも関わらず、使っていいよ！とGOを出してくれた会社にも本当に感謝です。

### アップデート内容の共有会
Figmaを日頃から使っている人が増えて来たように感じた辺りから、Figmaの新機能やアップデート内容を共有する会をちょこちょこ開催しました。（Dev Modeが登場したときは、社内でもかなり盛り上がりました！）

### 基本操作を叩き込む会
これまでの勉強会やハンズオンとは少し違って、Figmaを息をするように操作できるようになるために、ひたすら反復練習をする会も複数回開催しました。
サンプルの題材と主要なショートカットキー一覧を準備して、みんなで一緒にショートカットキーを押しながらひたすらボタンをオートレイアウトで作るなどを繰り返す、といった内容です。
操作に詰まったら秒で手を上げてください、というルールのもと、参加者みんなでわいわい練習しました。
開催後、操作が手に馴染むようになった・オートレイアウトと仲良く慣れた気がする、などなど嬉しいフィードバックをもらいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2487729/bc4356e0-6ce2-aff5-aafc-796b23a61b6c.png)

### まとめ
今では逆に「こんなことできるよ！」「こんなプラグインあるよ！」など教えてもらう機会もたくさんあり、Figmaについて語れる仲間が社内にたくさんいることがとても嬉しいです。
今後は、さらに組織的な目線でFigmaの運用をよりよく取りまとめていけないかな、なども考えて行きたいなと思っています。
Figma布教活動の旅は続く！
自動販売機に投入された硬貨の合計金額を表示するプログラム

```java:Jihan.java
class Jihan{
	public static void main (String[] args){
		
		int coin = Integer.parseInt(args[6]); // ７枚の硬貨を投入する
		int sumCoin = 0; // 投入金額の合計値
		
		// 1円玉,5円玉,それ以外の値に警告文をあたえる
		for (int i = 0 ; i < args.length ; i++){
			
			coin = Integer.parseInt(args[i]);
			
			if ( coin == 1 ){ 
				
				System.out.println("警告：1円玉は使えません");
				
			}else if( coin == 5 ){
				
				System.out.println("警告：5円玉は使えません");
				
			}else if( coin > 500 ){
				
				System.out.println("警告：" + coin + "は硬貨として適切な値ではありません");
				
				// 10円玉～500円玉の硬貨を足す
			}else if( coin == 10 || coin == 50 || coin == 100 || coin == 500 ){
				
				sumCoin += coin;
				
			}	
		}
					
		System.out.println("ただいまの投入金額は" + sumCoin + "円です");
	}
}
```

（感想）
今回は、タイトルに書いてあるプログラムを作成した。
配列とコマンドライン引数、for文、if elseを使った複合系だ。複数のコマンドライン引数を入力するときの動作を少し忘れていたので、やや時間がかかった。

反省点
１．複数のコマンドライン引数がある場合はfor文を使い、1つずつ取り出してif文の条件にかけていく以下の文を忘れていた
```java
// 1円玉,5円玉,それ以外の値に警告文をあたえる
		for (int i = 0 ; i < args.length ; i++){
			
			coin = Integer.parseInt(args[i]);
```

２．System.out.println()の位置を確認する

```java: 変更前
警告：1円玉は使えません
ただいまの投入金額は0円です
警告：5円玉は使えません
ただいまの投入金額は0円です
ただいまの投入金額は10円です
ただいまの投入金額は60円です
ただいまの投入金額は160円です
ただいまの投入金額は660円です
警告：777は硬貨として適切な値ではありません
ただいまの投入金額は660円です
```
```java: 変更後
警告：1円玉は使えません
警告：5円玉は使えません
警告：777は硬貨として適切な値ではありません
ただいまの投入金額は660円です
```
sumCoin += coin;の下に書いていたら上記のように出力された。変更後のほうが警告文が先に来ていて投入金額もすべて足されて出力されてすっきりしている。
[GAS] Backlogタスクの定期作成


# Backlog のタスク定期自動作成を GAS を使って実現した

## 1. スプレッドシートの準備

まず、スプレッドシートにタスクの情報を入力します。以下のような形式にします。

| タスクのタイトル       | タスクの詳細     | 起動条件1（月）   | 起動条件2（日）   |
|------------------------|------------------|-------------------|-------------------|
| ◯◯の更新（#YY年#MM月次）  | タスクの詳細説明 | プルダウン（毎月 or 3,6,9,12月） | 25                |

## 2. GAS の作成

スプレッドシートに関連付けた Google Apps Script（GAS）を使って、定期的にタスクを自動で作成するスクリプトを作成します。

```javascript
/**
 * Backlogタスクの定期作成（Googleスプレッドシートの一覧を元に生成）
 */
const API_KEY = 'MY_API_KEY';  // 自分のAPIキー
const PROJECT_ID = 'MY_PROJECT_ID';  // 自分のプロジェクトID
const SPREADSHEET_ID = 'MY_GOOGLE_SPREAD_SHEET_ID';  // スプレッドシートID
const SHEET_NAME = 'Googleスプシの画面下にあるシート名';  // シート名

// メイン関数：一覧走査 ＆ タスク生成
function createTasksFromSpreadsheet() {
  const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
  const data = sheet.getDataRange().getValues();

  const currentYear  = new Date().getFullYear();
  const currentMonth = new Date().getMonth() + 1;
  const currentDay   = new Date().getDate();

  // ヘッダー行をスキップ（行方向は1オリジンでループ）
  let title, desc, cond_1, cond_2
  for (let ii = 1; ii < data.length; ii++) {

    title  = data[ii][0];  // A列: タスク名
    title  = title.replace('#YY', currentYear);  // #YY を currentYear  に置き換え
    title  = title.replace('#MM', currentMonth); // #MM を currentMonth に置き換え
    desc   = data[ii][1];  // B列: 説明

    cond_1 = data[ii][2];  // D列: 起動条件1
    cond_2 = data[ii][3];  // E列: 起動条件2

    console.log("[" + ii + "] タスク名：" + title);
    console.log("　起動条件１：" + cond_1);
    console.log("　起動条件２：" + cond_2 + "日");

    if (cond_1 === '毎月' || (cond_1==='3,6,9,12月' && [3,6,9,12].includes(currentMonth))) {
      console.log(ii + "件目のタスクを処理する月です！");
      if (cond_2===currentDay) {
        console.log(ii + "件目のタスクを処理する日です！■ タスクを生成します ■");
        // API によるタスク作成
        createBacklogTask(title, desc);
      }
    }
  }
}

// Backlog へのタスク作成
function createBacklogTask(title, desc) {
  const url = 'https://pettyl.backlog.com/api/v2/issues?apiKey=' + API_KEY;
  
  const payload = {
    "projectId": PROJECT_ID,
    "summary": title,
    "issueTypeId": 2531668, // 課題種別ID（2531668はタスク）
    "description": desc,
    "priorityId": 3  // 優先度ID（例: 3=中）
  };

  const options = {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + API_KEY,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify(payload)
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    const jsonResponse = JSON.parse(response.getContentText());
    console.log('タスク作成成功: ', jsonResponse);
  } catch (error) {
    console.error('タスク作成エラー: ', error);
  }
}
```
【Rust】スコープとブロック

# はじめに

Rust におけるスコープとブロックは、プログラムの構造を理解する上で重要な概念です。適切なスコープとブロックを使用することで変数や関数などの有効範囲を制御し、プログラムをより効率的で可読性の高いものにすることができます。

# スコープとブロック

**スコープ**（Scope）はプログラム内で**定数や変数、関数などの要素が有効である（使用できる）範囲**を指します。一方、**ブロック**（Block）は **`{}` で囲まれた領域**を指します。

## スコープの基本

Rust では `{}` を使用して独自のスコープ（**ローカルスコープ**）を作成します。関数、ループ、条件式などでローカルスコープを作成することもできます。
`{}` で囲まれた領域は**ブロック**と呼ばれ、ブロックの中で宣言された変数や関数はそのブロック内でのみ有効です。

ローカルスコープ外の範囲は**グローバルスコープ**と呼ばれます。

### グローバルスコープ

グローバルスコープで宣言された変数や関数は**プログラム全体で有効**です。つまり、プログラムのどの場所からでも変数や関数を使用することができます。

```rust
// グローバルスコープ
const A: i32 = 20; // 定数

fn main() {
    println!("{}", A); // 定数を使用
}
```

この例では、定数 `A` はグローバルスコープで宣言されており、どのスコープからでもアクセスが可能です。

### ローカルスコープ

ローカルスコープで宣言された変数や関数は**そのスコープ内でのみ有効**です。Rust ではブロックや関数、ループ、条件式でローカルスコープを作成できます。

```rust
fn main() {
    let a = 10;

    {// 内側のスコープ
        let b = 20;
        // 現在のスコープの外側で宣言した変数(a)は使用できる
        println!("a: {}, b: {}", a, b);
    }
    // 内側のスコープで宣言した変数(b)は使用できない
    // println!("b: {}", b); // エラー: b はスコープ外
}
```

この例では、変数 `b` は内側のスコープで宣言され、そのスコープ内でのみ有効です。スコープが終了すると、変数 `b` は解放され、アクセスできなくなります。

## スコープのネスト

Rust ではスコープをネストすることができます。内側のスコープでは、外側のスコープで宣言された変数にアクセスできますが、その逆はできません。

```rust
fn main() {
    let x = 5;

    {// 内側のスコープ1
        let y = 10;

        {// 内側のスコープ2
            let z = 15;
            println!("x: {}, y: {}, z: {}", x, y, z);
        }
        // println!("z: {}", z); // エラー: zはスコープ外
    }
    // println!("y: {}", y); // エラー: yはスコープ外
}
```

この例では、変数 `x` は最も外側のスコープに宣言されているため、どの内側のスコープからでもアクセスできます。一方、変数 `y` は内側のスコープ 1 で宣言されているため、その内側のスコープ 2 からアクセスできますが、最も外側のスコープからはアクセスできません。変数 `z` は内側のスコープ 2 で宣言されているため、そのスコープ内でのみ有効です。

## 式としてのブロック

Rust におけるブロックは、単にスコープを形成するだけでなく、式（Expression）としても扱うことができます。

:::note
**式と文**
式（Expression）とは、**値を生成する**コードの断片です。`5 + 3` などです。
一方、文（Statement）はひとつの完結した命令です。文は値を返さず、単に実行される命令です。Rust において `;` は文の終わりを表す記号です。

```rust
      Expression
        -----
let x = 5 + 3; // `5 + 3` は式であり、`let x = 5 + 3;` は文
--------------
  statement
```

:::
式としてブロックを使うことで、複数の文をまとめて 1 つの式として評価することができます。

```rust
fn main() {
    let x = {
        let y = 5;
        let z = 7;

        // ブロックの最後に ; がないので式となり、その結果がブロックの値となる
        y + z
    };

    println!("x = {}", x); // x は 12 になる
}
```

## シャドーイング

Rust では、同じ名前の変数を再度宣言することができます。このプロセスを**シャドーイング**（Shadowing）と呼びます。

```rust
fn main() {
    let x = 5;
    println!("最初の x: {}", x); // 5

    // 同じスコープでシャドーイング
    let x = x + 1;
    println!("シャドーイング後の x: {}", x); // 6

    {
        // 内側のスコープでシャドーイング
        let x = x * 2;
        println!("内側スコープの x: {}", x); // 12
    }

    println!("最終的な x: {}", x); // 6
}
```

この例では、変数 `x` の値は最初 5 ですが、その後シャドーイングにより新しい `x` が作成されます。内側のスコープでもシャドーイングが行われ、新しい値が計算されます。ただし、スコープ内部でシャドーイングしてもスコープ外部に影響を与えません。
ABC382Bをjavascriptで解いた

# [今日の問題](https://atcoder.jp/contests/abc382/tasks/abc382_b)
↑押してください。
# 自分の回答(javascript)
```javascript
function Main(input){
    min = 1e18
    max = -1e18
    let abc = "abcdefghijklmnopqrstuvwxyz".split("")
    let ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
    let f = 3
    if(f == 0){
      input = parseInt(input.trim())
    }
    if(f == 1){
      input = input.trim().split("\n").map((a)=>parseInt(a))
    }
    if(f == 2){
      input = input.trim().split("\n").map((a)=>a.split(" ").map((b)=>parseInt(b)))
    }
    //ここより上は定型文です。
   input = input.trim().split("\n")
   let [n,k] = input.shift().split(" ").map((a)=>parseInt(a))
   let s = input.shift().split("")
   j = n-1
   for(let i = 0;i<k;i++){
     while(s[j] == "."){
       j --
     }
     s[j] = "."
   }
   console.log(s.join(""))
   }
  Main(require("fs").readFileSync(0, "utf8"));
  

```
# 工夫した点
右から順に見ていきます。wlile文で途中にある"."を飛ばします。"@"だったら"."にして次に進みます。
Pythonでのf-stringを活用した文字列フォーマットの使い方

Python 3.6以降で利用可能なf-stringは、簡潔で可読性の高い文字列フォーマットを提供します。本記事では、基本的な使い方から応用例までを解説します。

---

## f-stringとは？

f-string（フォーマット文字列）は、文字列の中に変数や式を直接埋め込むことができるPythonの機能です。以下のように、文字列の前に`f`または`F`を付けて使用します：

```python
name = "Alice"
age = 25
print(f"My name is {name} and I am {age} years old.")
# 出力: My name is Alice and I am 25 years old.
```

これにより、従来の`str.format()`や`%`演算子を使ったフォーマットよりも簡潔に記述できます。

---

## 基本的な使い方

### 変数の埋め込み

f-stringでは、波括弧 `{}` 内に変数をそのまま記述できます：

```python
language = "Python"
version = 3.10
print(f"I love {language} version {version}!")
# 出力: I love Python version 3.10!
```

### 式の埋め込み

波括弧内に式を記述することも可能です：

```python
x = 10
y = 5
print(f"The result of {x} + {y} is {x + y}.")
# 出力: The result of 10 + 5 is 15.
```

---

## 応用例

### フォーマット指定

f-stringでは、フォーマット指定子を使って表示形式を制御できます：

#### 小数点以下の桁数を指定

```python
pi = 3.14159
print(f"Pi is approximately {pi:.2f}.")
# 出力: Pi is approximately 3.14.
```

#### 数値をゼロ埋め

```python
number = 42
print(f"The number is {number:05}.")
# 出力: The number is 00042.
```

#### パーセンテージ表示

```python
accuracy = 0.98765
print(f"Accuracy: {accuracy:.2%}")
# 出力: Accuracy: 98.77%
```

### 辞書の値を参照

f-stringを使って辞書の値を参照することも可能です：

```python
data = {"name": "Bob", "age": 30}
print(f"Name: {data['name']}, Age: {data['age']}")
# 出力: Name: Bob, Age: 30
```

### 日付と時間のフォーマット

Pythonの`datetime`モジュールと組み合わせて使用すると、日時のフォーマットも簡単に行えます：

```python
from datetime import datetime
now = datetime.now()
print(f"Current date and time: {now:%Y-%m-%d %H:%M:%S}")
# 出力例: Current date and time: 2024-12-25 14:30:45
```

---

## 注意点

1. **Python 3.6以降が必要**  
   f-stringはPython 3.6で導入されたため、それ以前のバージョンでは使用できません。

2. **セキュリティに注意**  
   f-string内でユーザー入力を直接評価するのは危険です：

   ```python
   user_input = "__import__('os').system('rm -rf /')"
   # print(f"{user_input}") のようなコードは危険！
   ```

---

## まとめ

f-stringは、簡潔で強力な文字列フォーマット方法を提供します。本記事で紹介した基本的な使い方や応用例を参考に、日々のPythonコードで活用してください！

### 関連リンク
- [公式ドキュメント（英語）](https://docs.python.org/3/reference/lexical_analysis.html#f-strings)
- [Python 3.6 新機能リリースノート](https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep498)

---

最後まで読んでいただき、ありがとうございました！ぜひ、コメントやフィードバックをお寄せください！
ABC382Aをjavascriptで解いた

# [今日の問題](https://atcoder.jp/contests/abc382/tasks/abc382_a)
↑押してください。
# 自分の回答(javascript)
```javascript
function Main(input){
    min = 1e18
    max = -1e18
    let abc = "abcdefghijklmnopqrstuvwxyz".split("")
    let ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
    let f = 3
    if(f == 0){
      input = parseInt(input.trim())
    }
    if(f == 1){
      input = input.trim().split("\n").map((a)=>parseInt(a))
    }
    if(f == 2){
      input = input.trim().split("\n").map((a)=>a.split(" ").map((b)=>parseInt(b)))
    }
    //ここより上は定型文です。
   input = input.trim().split("\n")
   let [n,k] = input.shift().split(" ").map((a)=>parseInt(a))
   let s = input.shift().split("")
   res = k
   for(let i = 0;i<n;i++){
     if(s[i] == "."){
       k ++
     }
   }
   console.log(k)
   }
  Main(require("fs").readFileSync(0, "utf8"));
  

```
# 工夫した点
点の数とkを合計した数を求めればよいです。クッキーは食べる日より多くあるので大丈夫です。
JaSST'24 Tokai 参加レポート_基調講演編

# はじめに

こんにちは、本田技研工業遠野です。
ソフトウェア内製化チームでQAエンジニアをしています。（QA＝Quality Assurance、品質保証）

先日、ソフトウェアテストのシンポジウム”JaSST'24 Tokai”へ参加してきました。

## JaSST'24 Tokaiについて

開催概要はこちら

https://jasst.jp/symposium/jasst24tokai/outline.html

それぞれのセッションに参加しました。

- オープニング
- スポンサーセッション
- 基調講演
- ライトニングトーク
- 特別講演
- ワークショップ
- クロージング

最後のセッションは4つに分かれていたのですが、
わたしはワークショップの
【テスト設計初心者向け】テスト観点からテストケースを作ってみよう！
を選択しました

本記事は、基調講演についてレポートします。

# 基調講演：組織にテストを書く文化を根付かせる戦略

講演資料が公開されています。

https://speakerdeck.com/twada/building-automated-test-culture-2024-winter-edition

講演の内容は最後のスライドにもまとまっているので、ここではわたしが
また思い出したい内容や、感想について話します。

## 組織とソフトウェア

調査結果と、厳しい現実については他人事とは思えませんでした。
エリートのほうがスピートが速く質も高い、ローパーフォーマーはソフトウェアを外注している傾向がある旨などは特に覚えておきたいです。

また、前半の話からは「速さ」が大切だと思い聞いていました。
これまでは、品質がいいものをつくりたい、そのためにはまず試してみることが大切だ、と漠然と捉えていて
速いかどうかはそこまで気にしていませんでした。
上手い組織はみんな速いと聞いてしまったら、同じようにやりたくなってきましたね！（日本人です）

それはさておき「速さ」はモチベーションにしやすそうだと個人的には思います。
品質に取り組むときの観点としてもっておきたいです。

## 組織に根付かせるための作戦

人事評価と、「新人」教育については正直少し遠い話だと思っています。
一方で、すでにいる人たちへ対する「実際の例を使って」話す作戦は
いまの組織に合いそうだと思いました。
自社の事例として伝えられるよう考えてみようと思います。

## 技術が文化に影響を与える

自チーム（Hondaソフトウェア内製化チーム）はわたしも含めて中途入社のメンバーが多いので、文化をつくっていきやすい環境かもしれません。
とはいえまだまだ「ソフト」ではない、ハードなソフトウェアであるのが現状なので、
よいツール、よい考え方を使いながらよい文化をつくっていきたいですね。

# おわりに

「スピード」というヒントを得られたことが個人的には大きな収穫となりました。
また、能力は外注できない、上手くなるしかない、というところも頭の中に響いています。
大きな文化形成もまず手元の一歩だと思うので、目の前の担当プロジェクトとともに成長していきたいです。
ABC381Dをjavascriptで解いた

# [今日の問題](https://atcoder.jp/contests/abc381/tasks/abc381_d)
↑押してください。
# 自分の回答(javascript)
```javascript
function Main(input){
    min = 1e18
    max = -1e18
    let abc = "abcdefghijklmnopqrstuvwxyz".split("")
    let ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
    let f = 2
    if(f == 0){
      input = parseInt(input.trim())
    }
    if(f == 1){
      input = input.trim().split("\n").map((a)=>parseInt(a))
    }
    if(f == 2){
      input = input.trim().split("\n").map((a)=>a.split(" ").map((b)=>parseInt(b)))
    }
    //ここより上は定型文です。
   n = input.shift()[0]
   alist = input.shift()
   mae = -1
   ok = false
   list = []
   res = 0
   set = new Set()
   for(let i = 0;i<n;i++){
     //console.log(set)
     if(ok){
       if(!set.has(alist[i])&&alist[i]==alist[i+1]){
         count += 2
         i ++
         set.add(alist[i])
         res = Math.max(res,count)
       }else{
         if(set.has(alist[i])){
           if(alist[i] == alist[i-1]){
             count = 2
             start = i-1
             set = new Set()
             set.add(alist[i])
             continue
           }else{
             while(true){
               
               if(alist[start] == alist[i]){
                 start += 2
                 i++
                 break
               }
               set.delete(alist[start])
               start += 2
               count -= 2
             }
           }
         }else{
           mae = alist[i+1]
           i ++
           ok = false
           count = 0
           set = new Set()
         }
       }
     }else{
     if(alist[i] == mae){
       set.add(alist[i])
       count = 2
       ok = true
       start = i-1
       res = Math.max(res,count)
     }else{
       mae = alist[i]
     }
     }
   }
   console.log(res)
  }
  Main(require("fs").readFileSync(0, "utf8"));
  

```
# 工夫した点
計算量に注意する必要があります。尺取法かそれもどきてきなものを使います。最初から順に見ていって、連続する２つのアルファベットを見つけたらokをtrueにして尺取法を開始します。もし被っているアルファベットが見つかったら末尾を削除していきます。
Nuxt/Vite npm run devでlocalhostに繋がらないエラーの原因はESET！（MacM2）

## 事象
Nuxt3/ViteでWEBアプリを作成中、ChromeおよびBraveでhttp://localhost/ にアクセスするも時折下記の画面が発生し、プレビューできない現象が発生する。
![スクリーンショット 2024-12-25 14.37.07（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473627/fcb91a99-d4b4-08ab-010b-a5a9d6c04977.png)

:::note warn
__この画面__
このサイトにアクセスできません
localhostで接続が拒否されました。

次をお試しください
・接続を確認する
・プロキシとファイアウォールを確認する
ERR_CONNECTION_REFUSED
:::

色々調べた結果、__ESET__ が原因であると判明しました。

## 環境
- MacMini (Apple M2,2023)
macOS Sequoia(15.1.1)
- ESET CYBER SECURITY
バージョン（8.2.800.0）

## 解決方法
まず、[Mac環境で特定の通信が遮断される（「ファイアウォール機能」に起因する場合｜ESET公式HP）
](https://eset-support.canon-its.jp/faq/show/1583?site_domain=default)を参考に、ファイアウォールを`無効`にして、`Localhost`へのアクセスが正常に戻るか確認してください。

アクセスが戻れば、本方法が有効である可能性があります。

検証後はファイアウォールを、`有効`に戻すことを忘れないでください。

ちなみに上記リンクの公式HPの手順と一部被りますので、公式HPを参照してわかる方は、以降を読まなくても大丈夫だと思います。

### ブロックされているアプリを特定する
ブロックルールからブロックを除外すればよのですが、VSCodeやChromeを除外してもダメです。
実行アプリ本体を除外リストに入れないとダメなためです。

![スクリーンショット 2024-12-25 14.48.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473627/8b6cc321-9a78-30fa-cc87-b385c5d82d5c.png)
`ツール`→`ログファイル`と進みます。

![スクリーンショット 2024-12-25 14.48.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473627/e134e26e-a72a-6017-1a90-c2058d54fe09.png)
右上のプルダウンから`ファイアウォール`を選択します。

リストの中からブロックされているアプリを探ります。
今回私の環境では`node`アプリでした。
この時のpathを覚えておきます。

### 除外したいアプリを登録する
![スクリーンショット 2024-12-25 14.47.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473627/0edac283-13f1-d312-2b91-9f358886cc07.png)


画面左上の`ESET Cyber Security`→`設定`→`ファイアウォール`を選択します。

![スクリーンショット 2024-12-25 14.47.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473627/cbab3f3e-cd81-0538-9f31-4ae8c782a6ed.png)
`アプリケーションルール`を選択
![スクリーンショット 2024-12-25 14.47.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473627/4475816e-8850-d33f-4df9-9bc53ee36f09.png)
新たに開いたダイアログボックスから、左下の`+`をクリック、先ほどメモしたアプリのpathを辿ってアプリを選択します。

アプリの選択後、プルダウンを選択し`受信接続を許可する`に変更します。

最後に右下の`OK`を押してダイアログを閉じると設定が反映されます。

### 確認
`localhost`に戻るとアクセスできるようになっていると思います。

## あとがき
メジャーバージョンアップが半年くらい前？にあり、参考ページでは対応できなかったため、記事にしました。

新しくなってからもしばらくは正常に使用できていたため、おそらくマイナーアップデートによるバグだと思います。

しばらくしたら公式に修正されることを望みますが、これまでの対応を見る限り望み薄でしょう・・・

~~カスペルスキーは使いやすいかったなぁ~~

誰かの開発の役に立てれば幸いです。

## 参考ページ
- [ESETのファイアウォールが動作しているとDockerで立ち上げたlocalhostのページがブラウザで確認できない問題](https://qiita.com/miriwo/items/207de4783a88abd11c71)
- [【ESET】が原因！Dockerでlocalhostに繋がらないエラー(Mac)](https://qiita.com/Tii_dev/items/1086dc36b0144820eba5)
- [Mac環境で特定の通信が遮断される（「ファイアウォール機能」に起因する場合｜ESET公式HP）
](https://eset-support.canon-its.jp/faq/show/1583?site_domain=default)
New Relic アップデート(2024年11月)

2024年11月のNew Relic のアップデートをまとめて紹介です！APMのサマリー画面で、ブラウザのユーザー体験ようになったり、Query Builderの画面が大幅にアップデートしています！

## [APM] ブラウザにおけるユーザー体験の指標をAPM画面で一度に確認
APMのサマリー画面で、ブラウザのユーザー体験を把握する上で重要な指標であるCore Web VitalsやJavaScriptのエラーの発生状況を確認できるようになりました。バックエンドの指標とあわせて、シームレスなトラブルシューティングや分析をすることが可能になります。

![update202411-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485441/e9cd5145-6bb6-bb37-49e4-d788a5b56a58.png)

## [Query Builder] データ構造を確認しながらNRQLの作成やカスタマイズが可能に
Query Builderの画面にData Explorerが統合され、これまで以上に直感的にNRQLを作成してデータにアクセスできるようになりました。イベントやメトリクスを選択することでデータ構造を確認しながらNRQLを作成することも可能になりました。

![update202411-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485441/d3569ea5-a694-99d8-7d7b-903eaeadbc5e.png)

他のアップデートもまとめてブログでご確認ください。
↓↓↓↓↓↓

https://newrelic.com/jp/blog/nerdlog/new-relic-update-202411

- **2024年11月アップデート**
  - APM: ブラウザにおけるユーザー体験の指標をAPM画面で一度に確認
  - Query Builder: データ構造を確認しながらNRQLの作成やカスタマイズが可能に
  - APM: Java 実行時のJVMプロパティの難読化が可能に
  - Logs: カスタムタグをログに追加できるようになりました
米田の補題 #15 圏の例 モノイドの圏

# 米田の補題は、圏論でもっとも重要な定理です（繰り返し）
圏論は、数学の基礎理論です。いままで、[万物の理論](https://amzn.to/3ZLmCJH)
といわれていましたが、[数理科学 11月号](https://amzn.to/4iz6NgM)では、なんと　<font color="Red">万物・万事・万人</font>のための数学理論とまでいわれるようになりました
このAdventCalendar は、体験的に圏論の最も重要な定理である米田の補題を体験的に理解してもらうためにかいています

参考にしているのは、[圏論の道案内](https://amzn.to/4iH2Rus)です

# モノイドの圏
ますます数学的な話です。しょうがないのでモノイドという言葉は覚えましょう。自然数 + 足し算　はモノイドです。例として、自然数を提示してきました。モノイドは、とりあえず、自然数だと割り切りましょう。用語としては、マグマ、半群、モノイド、群などが代数構造の呼び名になります。覚えるのは大変なので、モノイドだけはまず覚えましょう。それで、**ちがうものおなじとみなすすごいこと**の触りを紹介します。モノイド準同型です。何がおいしいのかは、すみません、さきにすすまないとわかりません。

```math
{\LARGE MとM^\primeがモノイド準同型とは}\\
```
```math
{\LARGE集合の写像f:M->M^\prime}
```
</br>
が下記をみたすこと

$${\LARGE f(a∘_M b)=f(a)∘_M\prime(b)}$$

$${\LARGE f(1_M)=1_M\prime}$$

ようするに、合成と単位元０（射では、恒等射）が移れば準同型だというわけです。自然数＋足し算がわかりやすいです。１からはじめるかわりに２からはじめても、３からはじめても同じ構造でしょう。もちろん単位元０は残します。

**米田の補題川柳　モノイドは単位元こそ重要だ**
なんとなく単位元 つまり　恒等射が重要なんだなと思えてきたでしょうか？　ただこの状態だと、普段の企画会議をすすめるのに画期的に役立つには程遠いです。米田の補題は、証明ぬきで**関係は内容よりも重要だ**と説明した程度で、事実上は使えます。
ABC381Cをjavascriptで解いた

# [今日の問題](https://atcoder.jp/contests/abc381/tasks/abc381_c)
↑押してください。
# 自分の回答(javascript)
```javascript
function Main(input){
    min = 1e18
    max = -1e18
    let abc = "abcdefghijklmnopqrstuvwxyz".split("")
    let ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
    let f = 3
    if(f == 0){
      input = parseInt(input.trim())
    }
    if(f == 1){
      input = input.trim().split("\n").map((a)=>parseInt(a))
    }
    if(f == 2){
      input = input.trim().split("\n").map((a)=>a.split(" ").map((b)=>parseInt(b)))
    }
    //ここより上は定型文です。
    input = input.trim().split("\n")
    res = 1
   n = parseInt(input.shift())
   t = input.shift().split("/")
   mae = 0
   for(let i = 0;i<t.length;i++){
     ato = 0
     for(let j = 0;j<t[i].length;j++){
       if(t[i][j] == "2"){
         ato ++
       }else{
         break
       }
     }
     res = Math.max(res,Math.min(mae,ato)*2+1)
     mae = 0
     for(let j = t[i].length-1;j>=0;j--){
       if(t[i][j] == "1"){
         mae ++
       }else{
         break
       }
     }
     
   }
   console.log(res)
  }
  Main(require("fs").readFileSync(0, "utf8"));
  

```
# 工夫した点
"/"でsplitしてそれぞれの前と後での連続数の最大値を更新していきました。特に計算量の心配はありません。
ABC381Bをjavascriptで解いた

# [今日の問題](https://atcoder.jp/contests/abc381/tasks/abc381_b)
↑押してください。
# 自分の回答(javascript)
```javascript
function Main(input){
    min = 1e18
    max = -1e18
    let abc = "abcdefghijklmnopqrstuvwxyz".split("")
    let ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
    let f = 3
    if(f == 0){
      input = parseInt(input.trim())
    }
    if(f == 1){
      input = input.trim().split("\n").map((a)=>parseInt(a))
    }
    if(f == 2){
      input = input.trim().split("\n").map((a)=>a.split(" ").map((b)=>parseInt(b)))
    }
    //ここより上は定型文です。
   t = input.trim().split("")
   set = new Set()
   if(t.length%2 == 1){
     console.log("No")
     return
   }
   for(let i = 0;i<t.length;i+=2){
     if((!set.has(t[i]))&&t[i] == t[i+1]){
       set.add(t[i])
     }else{
       console.log("No")
       return
     }
   }
   console.log("Yes")
  }
  Main(require("fs").readFileSync(0, "utf8"));
  

```
# 工夫した点
愚直にやりました。すでにあらわれた文字はsetに保存しました。
C言語とpythonの実行速度の違い

# C言語とpythonの実行速度の違い
#### 始めに
C言語にある程度慣れてきてほかの言語にも興味が出てきてどんな違いがあるか気になって調べると、難易度やらどんな時に使うかなどが出てきましたが、実行速度の違いがありました。どれくらい違うのか気になったので調べてみたいと思います。

## コンパイル言語とインタプリタ言語
そもそも、プログラミング言語は2種類に分類できます。
c言語はコンパイル言語と呼ばれる言語です。コンパイル言語とは、プログラムコードを実行可能な形式に変換するために、コンパイラと呼ばれるツールを使用するプログラミング言語のことを言います。プログラミング演習の時間にたくさん使った `gcc 〇〇.c -o 〇〇`がコンパイル作業です。
一方で、Pythonはインタプリタ言語と呼ばれる言語です。インタプリタ言語とは、ソースコードを実行時に一行ずつコンパイルしながら実行するプログラミング言語のことを言います。
## 実行速度
c言語とPythonはそれぞれコンパイル言語とインタプリタ言語であることがわかりましたが、では実行速度の違いはどうでしょうか？
結論から言うとc言語のほうが速いです。上で記述したように、コンパイル言語は実行前にインタプリタ言語は実行中にコンパイルします。なので、先にコンパイルしているコンパイル言語のほうが速く実行できます。英語の長文を日本語で翻訳してから読んで理解するのと、英語のまま読んで理解するのでは前者のほうが理解するのが速いのと同じです。

## 実際にやってみた
c言語野ほうが実行速度が速いと思っても本当に早いのか？実際にやってみたいと思います。そもそもどうやって計るのか？思いつかなかったのでCHATGPTに聞いてみました。そしたらあるコードが返ってきました。
```C:C言語
#include <stdio.h>
#include <math.h>
#include <time.h>

int is_prime(int n) {
    if (n <= 1) return 0;
    for (int i = 2; i <= sqrt(n); i++) {
        if (n % i == 0) return 0;
    }
    return 1;
}

int count_primes(int limit) {
    int count = 0;
    for (int num = 0; num < limit; num++) {
        if (is_prime(num)) count++;
    }
    return count;
}

int main() {
    clock_t start_time, end_time;
    start_time = clock();
    int prime_count = count_primes(100000);
    end_time = clock();

    printf("Found %d primes.\n", prime_count);
    printf("Time taken: %f seconds\n", (double)(end_time - start_time) / CLOCKS_PER_SEC);
    return 0;
}

```

```py:Python
import time

def is_prime(n):
    if n <= 1:
        return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False
    return True

def count_primes(limit):
    count = 0
    for num in range(limit):
        if is_prime(num):
            count += 1
    return count

start_time = time.time()
prime_count = count_primes(100000)
end_time = time.time()

print(f"Found {prime_count} primes.")
print(f"Time taken: {end_time - start_time} seconds")

```
何のコードかというと、0から100,000までの素数をカウントしてそれにかかった処理速度を表示するというプログラムです。
とりあえずやってみようと思ってDebianで試してみました。
```:PYthonの結果
Found 9592 primes.
Time taken: 0.10423851013183594 seconds
```
1行目が素数の個数で下が処理にかかった時間です。なるほどと思いながら、次はc言語のほうもやってみました。
```:c言語
Found 9592 primes.
Time taken: 0.010333 seconds
```
素数の個数は同じで、かかった時間はなんと桁が一つ違う結果になりました。コードがもっと長くなれば実行時間の差がもっとはっきりわかると思います。

それもやってみたいですが、論理回路と電気電子回路の試験もあるのでまた別の機会に、、、
【Unity】AnimatorCrossFadeのすすめ

# はじめに
この記事は[Hamster Output Advent Calendar 2024](https://qiita.com/advent-calendar/2024/game_hamster)の15日目の記事です！

今回の記事は最近使い始めたAnimatorCrossFadeについて調べた内容です。

# 参考にしたリンク

https://unity-shoshinsha.biz/archives/tag/animator-crossfade

https://yutakaseda3216.hatenablog.com/entry/2016/08/19/112114

# 何ができるか

Animatorのステートからステートへの遷移をスクリプトから行うことができます。画像だと矢印で繋がっている部分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/a2305873-5447-0b72-bb53-2dbfa14259ac.png)

# 結論
早い段階で結論を書いておくと、Animatorの遷移図がぐちゃぐちゃになる問題を解決することができます。Animatorの見にくさで困っている方はぜひ、使って見てください。

# 使い方

書き方は以下の通りです。
```C#
animator.CrossFade(ステート名, 遷移にかかる時間, レイヤー番号, アニメーションの開始位置,);
```

ソースコードにするとこんな感じになります。レイヤーとアニメーションの開始位置は入力しなくても利用できます。

```C#
public class Test : MonoBehaviour
{
    [SerializeField]
    private Animator _animator;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Z))
        {
            _animator.CrossFade("Idle", 0.3f);
        }

        if (Input.GetKeyDown(KeyCode.X))
        {
            _animator.CrossFade("Walk", 0.3f);
        }
    }
}
```

実行して、ZやXを押してみるとAnimatorが切り変わります！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/7a2cc003-e960-b922-17eb-9402829f1b8c.png)

画像じゃあまり伝わらないけど滑らかにAnimationが切り替わっていることが分かる...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/37780651-97ba-44a0-be2e-d314cb64be75.png)


# メリット
・AnimatorでAnimationの矢印を作成する手間が無くなる
・Animatorがぐちゃぐちゃにならない
・Animationを追加するだけで良い

普通にAnimatorで遷移図を作ると大体こうなると思いますが...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/93b63185-9593-8392-c0ba-437f184161f6.png)

AnimatorCrossFadeを利用する場合、線を繋ぐ必要が無いのでAnimatorがスッキリします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/b12f3fdb-37dc-6346-387f-1c5d79f35a9f.png)

# デメリット
・ステート名の入力が面倒
・Animatorのレイヤー内を総当たりして確認しているらしく、Animationが多ければ多い程負荷がかかる

ステート名の取得が面倒な部分はEditor経由で取得も可能です。良さそうな記事もありました。

https://qiita.com/neusstudio/items/64fef4a9dd6d6a620681

# FixedInTimeについて
CrossFadeともう一つ、CrossFadeInFixedTimeというものがあり、CrossFadeは正規化された時間でCrossFadeFixedInTimeは実際の時間という違いがあるらしいです。

※この違いはよく分かっていない...💦

# まとめ
Animatorがとても綺麗になるので遷移図の見にくさで悩んでいる人は使ってみても良いかも...。

スクリプトから、制御できることから細かい調整もしやすいし。
Shellでディレクトリを作成

構成管理用shell

やりたいこと
・シェルを実行することでいつも同じディレクトリが作成される
・ディレクトリが既に存在する場合は作成しない
・ディレクトリを作成する前に確認を行う

---
背景
昔はローカル/STG/本番3環境だったので手動でコマンド実行していた。
しかし、今は環境が倍以上に増えたのでシェルで再現性あるディレクトリ作成を行いたい。
将来はこのシェルを構成管理ツールから実行することで楽をしたい。

この処理の前にchmodを入れることでディレクトリのパーミッションを変更可能
＞echo "ディレクトリ $dir を作成しました。"

```shell
#!/bin/bash

# 作成したいディレクトリ名をリストとして定義
directories=("dir1" "dir2" "dir3")

# 作成済みと未作成のディレクトリを格納する配列
existing_dirs=()
to_create_dirs=()

# ディレクトリの状態をチェック
for dir in "${directories[@]}"; do
  if [ -d "$dir" ]; then
    existing_dirs+=("$dir")
  else
    to_create_dirs+=("$dir")
  fi
done

# 結果を表示
echo "既に存在するディレクトリ:"
for dir in "${existing_dirs[@]}"; do
  echo "  - $dir"
done

echo "作成されていないディレクトリ:"
for dir in "${to_create_dirs[@]}"; do
  echo "  - $dir"
done

# y/n の入力を受け付ける
echo -n "作成されていないディレクトリを作成しますか？ (y/n): "
read -r answer

# y の場合はディレクトリを作成
if [[ "$answer" == "y" || "$answer" == "Y" ]]; then
  for dir in "${to_create_dirs[@]}"; do
    mkdir "$dir"
    echo "ディレクトリ $dir を作成しました。"
  done
else
  echo "処理を終了します。"
  exit 0
fi
```