OmniAICreator/Qiita-1.07M huggingface dataset:
Snowflake のタスクの実行プログラムを外部ファイル化する方法

# 概要
　Snowflake で，テーブルやデータマートを更新する際，[タスク機能](https://docs.snowflake.com/ja/user-guide/tasks-intro)を用いると定期実行（自動更新）が可能である．また，更新のSQLやPythonプログラムをタスク化する際，そのプログラムを[ストアドプロシージャ](https://docs.snowflake.com/ja/developer-guide/stored-procedure/stored-procedures-overview)で関数化しておくと便利である．
　以下は，ストアドプロシージャ内にSQLプログラムを記載し，その関数をタスクで毎日午前0時に呼び出している．
```
CREATE OR REPLACE PROCEDURE <PROCUDURE>()
RETURNS VARCHAR NOT NULL
LANGUAGE SQL
AS
$$
BEGIN
  CREATE OR REPLACE TABLE <TABLE_NAME> (
      id INT,
      name STRING
  );  
  RETURN message;
END;
$$
;

create or replace task TASK
    warehouse=<WAREHOUSE_NAME>
    schedule='using cron 0 0 * * * UTC'
    as call <PROCEDURE>;
```
　しかしながら，このためには，[ストアドプロシージャの権限](https://docs.snowflake.com/ja/user-guide/security-access-control-privileges#stored-procedure-privileges)と[タスクの権限](https://docs.snowflake.com/ja/user-guide/security-access-control-privileges#task-privileges)が必要になる．ユーザにこの権限を渡せない場合，システム管理者がこのタスクを作成する必要がある．その回避策として，プログラムを外部ファイル化し，ユーザがそのファイルを編集できるようにする方法を紹介する．ただし，システム動作の間にユーザが介在することになり，システム側とユーザ側の責任を分離できなくなるため，あまりお勧めはしない．

# サンプルコード（SQL編）
## プログラムをSnowflake 内部ステージにアップロードする
 ```SQL
CREATE OR REPLACE TABLE <TABLE_NAME> (
    id INT,
    name STRING
);  
 ```
アップロードしたファイルのパスをメモする．
例：'@"\<DATABASE_NAME\>"."\<SCHEMA_NAME\>"."\<STAGE_NAME\>"/\<FILENAME\>.sql'

## ストアドプロシージャとタスクの作成
 ```
CREATE OR REPLACE PROCEDURE <PROCUDURE>()
RETURNS STRING
LANGUAGE SQL
AS
$$
BEGIN
    execute immediate from '@"<DATABASE_NAME>"."<SCHEMA_NAME>"."<STAGE_NAME>"/<FILENAME>.sql';
    RETURN 'successfully';
  RETURN message;
END;
$$
;

create or replace task TASK
    warehouse=<WAREHOUSE_NAME>
    schedule='using cron 0 0 * * * UTC'
    as call <PROCEDURE>;
 ```
これにより，ユーザにストアドプロシージャの権限とタスクの権限を付与することなく，ユーザ側で任意のSQLプログラムを定期実行することができる．

# サンプルコード（Python編）
## プログラムをSnowflake 内部ステージにアップロードする
 ```Python
import snowflake.snowpark as snowpark
from snowflake.snowpark.functions import col

def main(session: snowpark.Session): 
    
    tableName = 'information_schema.packages'
    dataframe = session.table(tableName).filter(col("language") == 'python')
    
    dataframe.write.save_as_table(f"{<DATABASE_NAME>}"."{<SCHEMA_NAME>}"."{<TABLE_NAME>}") 
    return dataframe
 ```
アップロードしたファイルのパスをメモする．
例：'@"\<DATABASE_NAME\>"."\<SCHEMA_NAME\>"."\<STAGE_NAME\>"/\<FILENAME\>.py'

## ストアドプロシージャとタスクの作成
 ```
CREATE OR REPLACE PROCEDURE <PROCUDURE>()
returns TABLE()
language python
runtime_version = '3.11'
PACKAGES = ('snowflake','snowflake-snowpark-python')
handler = '<FILENAME>.main'
imports = ('@"<DATABASE_NAME>"."<SCHEMA_NAME>"."<STAGE_NAME>"/<FILENAME>.py')

create or replace task TASK
    warehouse=<WAREHOUSE_NAME>
    schedule='using cron 0 0 * * * UTC'
    as call <PROCEDURE>;
 ```
これにより，ユーザにストアドプロシージャの権限とタスクの権限を付与することなく，ユーザ側で任意のPythonプログラムを定期実行することができる．
【Power Automate編】開発補助ツールまとめ

これまで作成した開発を補助するための数式ジェネレーターやツールをまとめました。
随時更新中かつ不具合報告お待ちしております。(年末年始に改修・アップデート予定)

これらのツールは生成AIで作成しています。テストしてある程度使えるレベルにしていますが、バグやエラーがあれば教えてください。
情報を抜き取るような機能はないですが、機密情報などの入力には注意してください。

## フィルタークエリ生成ツール

使用時の注意：
・列名は内部名で指定し、文字列を指定するときは''(シングルコーテーション)で囲ってください。
・startswithのBとsubstringofのAには文字列を入力してください。
・フィルタークエリを複数条件(or, and)にしたいときは、生成された数式をorやandでの両側につなげて入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/681ba7a5-9396-227f-822b-daf0bb9b0e5c.png)

https://powerplatformnikki.com/copypastefilterquery/

## 選択式数式生成ツール(日時)

面倒な日時計算・表示系の数式を選択式で自動生成できるようにしています。

https://powerplatformnikki.com/copypastedateconverter/

## Power Apps編はこちら

https://powerplatformnikki.com/powerappssupporttool/

## 元記事 

https://powerplatformnikki.com/powerautomatesupporttool/
【第1回】Pythonで語頭符号の実装【情報理論】

# はじめに

情報理論における最大のテーマは`圧縮`と`誤り訂正`でした。
それでは、符号理論の基礎である`語頭符号`について学んでいきましょう。

## 符号についての概要

符号化とは送りたい文字列を0と1で表現することでした。例えば、

|a  |b  |c  |
|:-:|:-:|:-:|
|0  |10  |11  |

を使って「abc」を符号化すると「01011」になります。これを復号化すると「abc」に戻りますね。では、次の場合はどうでしょうか？

|a  |b  |c  |
|:-:|:-:|:-:|
|0  |1  |01  |

「abc」の符号は「0101」になりますね。これを復号化してみてください。結果は「abc」と「abab」と「cab」と「cc」になってしまうんです。このように符号空間の設計によっては復号化で失敗してしまうことがあります。これを解決するために語頭符号を学んでいきましょう。

## 語頭符号とは
``記号の符号の先頭が他の符号語と同じでない符号空間``のことを指します。例えば上の2つ目の符号空間では aの**0** が cの**0**1 の先頭となっているので、語頭符号**でない**です。他にも「**0101**」と「**0101**10」のような場合でも語頭符号**でない**例です。
一方、上の1つ目の符号空間は語頭符号です。

### メリット
語頭符号のメリットは必ず復号結果が一つに定まるということです。せっかく送ったデータの復号結果が複数あったら困りますよね。

例えば、上の1つ目の符号空間は語頭符号です。

一方、上の2つ目の符号空間では aの**0** が cの**0**1 の先頭となっているので、語頭符号**でない**です。
他にも「**0101**」と「**0101**10」のような場合でも語頭符号**でない**例です。

## 演習問題

### 1. 次の関数を作りなさい。

任意の符号空間で文字列を符号化する関数

入力: `符号化する文字列`, `記号列`, `符号列`
出力: `符号化した文字列`

####  例

入力: `'abc'`, `['a','b','c']`, `['0','10','11']`
出力: `'01011'`

### 2. 次の関数を作りなさい。

語頭符号な任意の符号空間で文字列を復号化する関数

入力: `復号化する文字列`, `記号列`, `符号列`
出力: `復号化した文字列`

####  例

入力: `'01011'`, `['a','b','c']`, `['0','10','11']`
出力: `'abc'`

### 3. 次の関数を作りなさい。(めっちゃむずい)

任意の符号空間で文字列を復号化する関数

入力: `復号化する文字列`, `記号列`, `符号列`
出力: `復号化した文字列の配列`

####  例

入力: `'0101'`, `['a','b','c']`, `['0','1','01']`
出力: `['abab','abc','cab','cc']`


## 解説
### 1, 2
おそらく簡単な問題だったと思います。基本的に左から文字を置き換えていくだけでできる問題でした。また、復号化に関しても**語頭符号**を条件としているので複雑な処理は不要でした。それでは答えを見ていきましょう。

次のコードでは`start`と`end`の範囲にある文字列が`symbols`の入っている時、対応する符号語に置き換えています。その後`start`の位置を更新して同じことを繰り返していきます。

```encode.py
def encode(text, symbols, signs):
   result = ''
   start = 0
   end = 0
   length = len(text)
   while end <= length:
      if (text[start:end + 1] in symbols): 
         result += signs[symbols.index(text[start:end + 1])]
         start = end + 1
         end = start
      else:
         end += 1
   return result
```


```decode.py
def decode(text, symbols, signs):
   result = ''
   start = 0
   end = 0
   length = len(text)
   while end <= length:
      if (text[start:end + 1] in signs):
         result += symbols[signs.index(text[start:end + 1])]
         start = end + 1
         end = start
      else:
         end += 1
   return result
```

### 3
この問題の難しさは結果が複数存在してしまうことです。語頭符号の良さがわかると思います。それでは答えを見ていきましょう。

次のコードは再帰処理を用いて、**もし一致する文字列があればそれ以降の文字列を同じ関数に実行**し、また、そうであってもそうでなかったとしても文字の長さを一文字増やして同じことをしていくという構想です。もし、最後の処理で一致するものがなければそのまま破棄されます。

```decode_super.py
def decode_super(text, symbols, signs, instance = '' ,stack=[]):
    end = 0
    length = len(text)
    if length <= 0:
        stack.append(instance)
    while end < length:
        if (text[0:end+1] in signs):
            decode_super(text[end+1:], symbols, signs, instance + symbols[signs.index(text[0:end+1])], stack)
        end += 1
    return stack
```

## 次のステップ

次の講義では符号の木を使っていきましょう。**とてもとても超超めちゃめちゃ大事**な手法なので、是非トライしてみてください。
【序章】Pythonで符号化を実装する【情報理論】

# はじめに

この記事シリーズでは、情報理論分野について深掘りしていきたいと思います。普段、何気なく使っているインターネットやスマートフォン、テレビやラジオの通信技術など、実はその背後には情報理論が大きな役割を果たしています。
情報理論は、データをいかに効率的に伝えたり、圧縮したり、誤りを訂正したりするかを扱う学問です。例えば、動画や画像がどうしてあんなに圧縮されているのか、どうして通信中にエラーが起きてもデータが無事に届くのか—そんな疑問を解決する手がかりがこの理論にあります。
これから、情報理論の基本的な概念や、実際のアルゴリズムに関する話題を紹介していく予定です。興味がある方は、ぜひ一緒にこの分野を学んでいきましょう。

## このシリーズの目的

1. 情報理論の基礎概念を理解する
2. Pythonの実装を通じて、符号化の実際的なメカニズムを学ぶ
3. コンピュータで符号化を自ら実装し応用できるようにする

## シリーズの構成

このシリーズでは、情報理論を以下の2つの主要なカテゴリに分けています。本シリーズは**演習&講義形式**でやっていきます。Pythonについて**少し**知っていることを前提としていますが、説明を見るだけでもなんとなくつかめると思います。

各記事の前半では演習問題を出しているのでトライしてみましょう。

### 1. データ圧縮

情報量を削減しながら元のデータを効率的に表現する技術を扱います。以下のテーマを難易度順に進めます。

1. **語頭符号**: データ圧縮における最も基礎的な符号化方式
2. **符号の木とシャノン符号**: ハフマン符号の基礎となる概念と情報理論に基づく符号化方式
3. **ハフマン符号**: 最適な符号長を持つデータ圧縮技術
4. **ブロックハフマン符号**: ハフマン符号の拡張版で、固定長ブロックに対応
5. **多元ハフマン符号**: ハフマン符号の多元対応版
6. **算術符号**: データの分布に基づく高効率な符号化手法
7. **Jones符号**: 算術符号を応用した特殊な圧縮手法
8. **LZ78符号**: 辞書ベースのデータ圧縮技術

### 2. 誤り訂正

データの損失やエラーに対処する技術を中心に学びます。以下のテーマをわかりやすい順序で進めます。

1. **パリティチェック符号**: 基本的なエラー検出符号
2. **ハミング符号**: 単一ビット誤りを訂正可能な符号
3. **リード・ソロモン符号**: ブロックエラー訂正に優れた符号
4. **畳み込み符号**: シーケンスデータ向けの符号化方式
5. **ターボ符号**: 高いエラー訂正能力を持つ符号
6. **LDPC符号 (低密度パリティ検査符号)**: 現代の通信で広く利用される高効率なエラー訂正符号
7. **ゴレイ符号**: 高度なエラー訂正を可能にする符号
8. **ファウンテン符号**: 欠落データの再構築に強い符号

これらのトピックを通じて、データ圧縮と誤り訂正の理論と実践を深く理解できるようになることを目指します。

## 次のステップ

次の記事では、Pythonの基礎コードを用いて、符号化の基本的な実装を行います。特に手を動かして実装していくことが大事ですので、与えられた問題のトライしてみてください！
【JavaScript】Meta 製 JS エンジンの Hermes を調査する

# はじめに

こんにちは、梅雨です。

今回は、Hermes という JavaScript エンジンについて調査を行ったので、それらの内容をまとめてみました。

# Hermes とは？

**Hermes** は、Meta（旧 Facebook）が開発した軽量で高速な JavaScript エンジンです。

特に React Native 向けに最適化されており、モバイルアプリケーションのパフォーマンス向上を目的としています。

https://github.com/facebook/hermes

# Hermes の特徴

まずは Hermes の主な特徴から見ていきましょう。

## Ahead-of-Time Compilation

Hermes は、JavaScript のソースコードを実行時ではなく、事前にバイトコードへコンパイルする **Ahead-of-Time Compilation（AOT）コンパイラ**の仕組みを採用しています。

これにより、アプリ起動時間の短縮やメモリ使用量の削減が実現されています。

反対に、実行時にコンパイルを行うコンパイラのことを **Just-in-Time Compilation （JIT）コンパイラ**と呼び、Google 製のエンジンである [V8](https://v8.dev) や Apple 製の [JavaScriptCore（JSC）](https://developer.apple.com/documentation/javascriptcore) ではこの JIT コンパイラの仕組みが採用されています。

:::note warn
V8 エンジンは JavaScript だけではなく WebAssembly のエンジンでもあり、こちらは AOT コンパイラの技術が採用されています。
:::

React Native の利用はモバイルアプリケーション開発という目的が明確であるため、最終的な実行環境も Android と iOS に限られています。そのため、ソースコードを事前にコンパイルするような仕組みが可能となっています。

## ガベージコレクション機能

また、Hermesは効率的な**ガベージコレクション**機能を備えており、低リソース環境でも動作可能です。

ガベージコレクションとは、プログラムが使用しなくなったメモリ領域を自動的に解放する仕組みです。使用されなくなったメモリを解放せずに放置すると、メモリリークが発生し、最終的にはシステムのパフォーマンスを低下させてしまう恐れがあります。

Hermes には **Hades** というガベージコレクション機能が備わっており、JavaScript コードを実行しているインタプリタのバックグラウンドスレッドでガベージコレクション作業を行うことでより短い休止時間を達成する仕組みが取られています。

https://github.com/facebook/hermes/blob/main/doc/Hades.md

# Hermes の欠点

続いて、現状考えられる Hermes の欠点について触れていきます。

## ECMAScript 2015 の不完全なサポート

2024年12月25日現在、Hermes は ES6（ECMAScript 2015）のほとんどの機能に対応していますが、完全な準拠には至っていません。

https://github.com/facebook/hermes/blob/388376f05d0c2c836c8761e372fdfafd9bf077fc/doc/Features.md

これはエンジンの軽量化とパフォーマンス最適化を優先するための設計上の選択であり、with 文や動的な eval() 関数などの一部の機能は**意図的に**サポートされていません。

ですので、完全な欠点とは言えないですが、他のエンジンに劣る部分となっています。

React Native のプロジェクトでこれらのコードを使用する場合は、残念ながら Hermes ではなく JSC を用いたコンパイルをする必要があります。

## QuickJS との比較

Hermes と比較可能な新興の JavaScript えnとして、**QuickJS** が挙げられます。

https://bellard.org/quickjs/

QuickJS は最新の ECMAScript の仕様に完全にキャッチアップしており、特に国際化 API（Intl）の使用を必要とするプロジェクトでは採用の候補になり得ます。

また、QuickJS は数百 KB という非常に小さいサイズのエンジンであるため、IoTやリソース制約の厳しい環境で JavaScript エンジンを必要とする場合には重宝されます。

現状想定されている用途が Hermes と QuickJS では異なるためそもそも性能の比較をすることに意味がないという意見もあると思いますが、今後 Hermes が JS エンジンとして活躍する領域を広げていくためには、このような問題を解消していく必要があるのではないかと考えました。

（参考）QuickJS やその他エンジンの性能比較ベンチマーク

![Screenshot 2024-12-25 at 20.44.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671591/cf933d41-b274-4785-2573-b91ce5eae195.png)


# 今後の可能性

Hermes は、現在 React Native に特化したモバイルアプリケーション向けの JavaScript エンジンとして、その軽量性とパフォーマンスを武器に成長を続けています。しかし、競合の JavaScript エンジンやそれらのエコシステムとの比較においては、今後さらに進化する余地があると思います。

まず、Hermes が React Native 以外の領域、例えばIoTやエッジコンピューティングへの展開を目指す場合、現行の仕様に加えて新たな対応が求められます。

特に、国際化 API や eval() 関数などの動的コードの実行といった機能がサポートされれば、モバイルアプリ以外の分野でも利用可能性が広がると考えられます。

さらに、React Native 自体がネイティブモジュールや新しいUIフレームワークとの統合を通じた進化を遂げることで、Hermes がモバイルアプリケーション開発のデファクトスタンダードとしての地位を固める可能性があります。

# おわりに

今回の記事では、Meta 製の JavaScript エンジンである Hermes を調査し、今後どのような発展が見込まれるかを考えました。

この先、Hermes が持つ軽量性や効率性の強みを活かしながら、新たな領域やエコシステムでどのような成長を遂げるかは非常に興味深いです。

最後までお読みいただきありがとうございました。
【楽しく学ぼう】AWS Cloud Quest やってみた

## AWS Cloud Questってなに?
AWSのブログより引用

>さて皆様、AWS クラウドの学習を、ゲームベースで行うことができる学習コンテンツの「AWS Cloud Quest」をご存じでしょうか？ゲーム内で、ストーリーに沿って出題されるソリューション構築に関する課題を、実際のAWSのアカウントを使用しながら解いていく、RPGテイストのコンテンツです。 

つまり、ハンズオン形式かつゲーム感覚でAWSを勉強していくことで理解を深めていくことができる
コンテンツです。

AWS Cloud Questでは、実際に無料のAWSアカウントを操作しながら AWSのサービスについて学習することができるので気軽に始めることができます。
課題ごとに、AWSアカウントが払い出されるので、**自分のAWSアカウントは不要**なのは嬉しいですね!

## 実際にプレイしてみて
まずは、初期設定は英語のため、日本語に変更します！
Settings > Language で言語設定画面に飛んで日本語に設定を変えます。

![スクリーンショット 2024-08-24 21.22.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/f2ba50c9-971f-61c6-3eaa-cfba577dbf02.png)

さて、ゲームをスタートしていきましょう。

無料で選択できるコースは`Cloud Practitioner`になるのでそちらで課題を選択していきます。

![スクリーンショット 2024-08-25 0.07.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/b5db5c92-b99c-4eb0-300a-daee7ca7d81c.png)

そしてアバターを作成していきます

![スクリーンショット 2024-08-25 0.11.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/5be3490e-a626-df1f-ec6b-8b208fa22823.png)

そして作成後クエストを引き受けると学習をスタートすることがでいます。

今回取り扱うサービスの概要を動画形式で学ぶことができます!
動画は英語ですが、字幕をつけられるので安心です。


![スクリーンショット 2024-08-25 0.14.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/910fce88-f1fe-f547-7c95-6423383961c1.png)

![スクリーンショット 2024-08-25 0.17.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/505ac29e-0ab8-c489-02dd-40967d3703c3.png)

さて、ここまで来たら概要を確認して実践していきます。
簡単なファイルのRenameから始まりアクセス許可のポリシーファイルの説明等をみながら
作業の方を行なっていきます。

クエストごとに時間制限があるので、そこは注意してください!

|![スクリーンショット 2024-08-25 0.27.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/dbbcfbe8-c99b-0508-d18b-af7d575d1d3d.png)| ![スクリーンショット 2024-08-25 0.27.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/177b1af1-e255-9418-3afc-75909537dfea.png)|
|--|--|

最後にDIY、課題を見ながら実際にソリューション検証を行なっていきましょう。
![スクリーンショット 2024-08-25 0.35.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/1cba5c5a-9149-4169-5a4a-34849ef3f177.png)

レベルも上がり、バッジを獲得できます。

|![スクリーンショット 2024-08-25 0.43.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/7ee33bdf-b982-1d1d-cda9-69ab12486189.png)|![スクリーンショット 2024-08-25 0.44.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636995/a93f44e2-1252-372e-5d41-69c149875c2f.png)|
|---|---|


## 所感
実際に、運用するのが怖いという初学者の人は、このようなゲーム形式で学習することで
楽しく学ぶことができると思います。

AWS Cloud Quest はあくまでゲームなので、**失敗しても誰にも迷惑がかからない** というのがすごく良いですね。

単純にドキュメントを読むだけだと、頭から抜けてくことも多いので
**楽しく・気軽に・実践的に** 学ぶことができるのはとても良いです。

自分は、SAAの資格の期限が切れそうなので再度勉強し直すのに使おうと思います。

## 参考
https://aws.amazon.com/jp/blogs/news/aws-cloud-quest-jp-is-now-available/

https://aws.amazon.com/jp/training/digital/aws-cloud-quest/
コラッツ予想のプログラム

一時期コラッツ予想にはまっていたので、その当時作成したCプログラムです。
```C:collatz.c
/*** The case that the value is odd forever ***/
// L--> (3m+1)/2 -> (3m'+1)/2 -> (3m''+1)/2

// n[=1n+0] -> ((3/2)^1)n+(1/2) -> ((3/2)^2)n+(5/4) -> ((3/2)^3)n+(19/8)
// -> ((3/2)^4)n+(65/16) -> ((3/2)^5)n+(211/32) -> ...

// |f(n) = a_n * m + b_n    |
// |a_n = (3/2)^(n-1)       | => f(n) = (m+1) * 3^(n-1) / 2^(n-1) - 1
// |b_n = (3/2)^(n-1) - 1   |   *** Of course, f(n) is integer ***
// 2 and 3 are coprime -> (m+1)/2^(n-1) is integer and 2^(n-1) <= [less than or equal] (m+1)

/*** This program algorithm ***/
// need to check odd
// 3->5, 5->8(even), 7->11, 9->14(even), 11->17, 13->20(even), 15->23,...
// L--> need to check 3,7,11,15, ..., 4n-1

#include <stdio.h>
#define VALUE 100000

int main(void) {
  for (int i = 1; i < VALUE; i++) {
    unsigned init = 4 * i - 1;
    printf("%u", init);  // initial state: 4n-1

    // 4n-1(odd) -> 6n-1(odd) -> 9n-1(even or odd)
    unsigned long int temp = 9 * i - 1;
    printf(",%lu", temp);

    while (temp > init) {
      if (temp % 2) {
        temp = (3 * temp + 1) / 2;
      } else {
        temp /= 2;
      }
      printf(",%lu", temp);
    }
    printf("\n");
  }
}
```
実行結果
```
3,8,4,2
7,17,26,13,20,10,5
11,26,13,20,10
15,35,53,80,40,20,10
19,44,22,11
23,53,80,40,20
27,62,31,47,71,107,161,242,121,182,91,137,206,103,155,233,350,175,263,395,593,890,445,668,334,167,251,377,566,283,425,638,319,479,719,1079,1619,2429,3644,1822,911,1367,2051,3077,4616,2308,1154,577,866,433,650,325,488,244,122,61,92,46,23
...
```

まあ、なんか収束の規則ないかなあと思って作ったものです。
```
// need to check odd
// 3->5, 5->8(even), 7->11, 9->14(even), 11->17, 13->20(even), 15->23,...
// L--> need to check 3,7,11,15, ..., 4n-1
```
の通り、奇数を調べるのですが、その中でも交互に次に偶数がくるので、$4n-1$について列挙する、というものになっています。

んで、次のステップ行くときも、偶数になる過程はすっとばして表示しています。

どうやら、ほとんどの数については成り立つようですが、完全証明には至ってないようです。
最近、ソファ問題が証明されたかも、と話題になったので、ひそかに着々と証明が進んでいるのかもしれません。
ControlDesk計測と同時にカメラを連動

## 1. はじめに
計測中の様子をカメラで録画するときってありますよね．
別に撮るだけだったら特に苦ではないですが，計測データと録画映像とをリンクさせるとなると話が別です．
後でスタート位置が合うように調整するという，とてつもなく面倒な作業が待っています．
だったらそもそも計測開始時に録画を開始すればいいのではというお話です．

## 2. 必要なもの
- USBカメラ
- OpenCVライブラリ

## 3. 記述
まず，USBカメラのcapture IDを取得します．
```python
import cv2

for i in range(20):
    cap = cv2.VideoCapture(i)
    if not cap.isOpened():
        continue 
    print(f"Camera {i}: {cap.get(cv2.CAP_PROP_FRAME_WIDTH)}x{cap.get(cv2.CAP_PROP_FRAME_HEIGHT)}")
    cap.release()
```
実行結果は後程．

以下のコードを実行すると別画面で録画始まり，Enterキーで終了します．
```python
import cv2
import time

cap = cv2.VideoCapture(2, cv2.CAP_DSHOW)
    
fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
fps = 30
size = (640, 360)
    
write = cv2.VideoWriter("C:/path/to/file/hoge.m4v", fmt, fps, size)
    
while True:
    ret, frame = cap.read()
    frame = cv2.resize(frame, size)
    write.write(frame)
    cv2.imshow('WebCam', frame)
        
    if cv2.waitKey(1) == 13:
        break
write.release()
cap.release()
cv2.destroyAllWindows()

```

後は，スレッドやRecodingの呼び出しと組み合わせれば完成です．

## 4. おわりに
USB出力でない一眼レフなどとも連動したいところです．
【雑談】ありがちなSESの特徴

2023年4月1日。就活を大サボりした自分。
なんとなくITが良いんじゃないかという理由で滑り止め中小SESに入社した。

その後常駐先や本社に感じた違和感を紹介しよう。
学生の人は入社する前のギャップを埋められるかも！

前提としてこれらを全く感じない優良SESも存在するからね！
一概にSESすべてをあてはめないように！


### ①会社の目標が共有されない
：社員への待遇ばかりを主張して、組織としての方向性が定まっていない。給料や成長など
　を強調するが、アピールポイントがそこだけだと待遇の良い別会社に行くのでは？
### ②評価制度
：普段全くかかわらない本社の上司が評価を下す。客先常駐とかだと特に違和感を感じる。
　逆に評価する側も大変なのでは？
### ③不健康
：肉体的にも精神的にも不健康そうな人が多数存在。
　下請け企業の悲しき現状よ。。。
　エンジニアになって一人作業が多くなっても見た目は大事。

### ④案件単価が社員に公開されない・案件の説明がない
：これは会社によって異なるが、隠す企業は危ないと思って良い。
　成長度合いや目標の指標になるよ。

### ⑤Webページの内容が抽象的
：これは、受注案件に統一性がないとこうなっている。
　案件を取得するにあたっての中長期的な目標がないと、
　Webページで主張することが不明瞭になる。
　単価の大きさや労働条件のみに着目した案件選びをするほど、このような傾向になる。

### ⑥常にトイレが満席
：常駐先によるが、主に50,60代の人が多い。
　仕事が振られていないか、本当におなかが痛いか、何かから逃げているか。

### ⑦元エンジニアが社長
：これも社長によって大きな差がある。
　エンジニア経験者だからエンジニア目線の良い経営ができるとは限らない。
　　
### ⑧声が異常に小さいか、異常に大きいか
：聞き下手と話し下手が混在している。
　足して二で割ると丁度良いね。

### ⑨案件先の良し悪しは「運」と考える文化
：案件先の相性は運ではない。その案件を選んだ上司・人事の責任である。
　部下がその環境下で長期間働くのに対して、上司のリスク意識が無さすぎる。
　良いように扱われすぎないように。



#### 終わりに
ネガティブな内容になってしまったが、悪いことばかりじゃない。
違和感を一つ一つ正していけば良い。
今回は忘れないためにここに記録した。
誰かのためになればと共有もしておく。
ragas: Exception raised in Job[-]: TimeoutError() は、LLM の 利用上限でもあった

# 背景

`TimeoutError ` が直らないので、ちゃんと log を確認してみたら・・

429 エラーが出いてたっていう、おバカな記録

https://qiita.com/baku2san/items/d26e4c58b99666ae2943

# 結論

ログを見て、以下のようになっていれば、LLM の 利用制限になっていたって話だと思われる。

> DEBUG:openai._base_client:Retrying due to status code 429


# 対策

Azure OpenAI Service だったので、RPMを上げて解消

今回は、4o/4o-mini で、10k としていたので、上限を挙げたが・・429 がなくなるまでは上げてない :thinking: 
1. 100k にしたことで、Timeout は消えた
1. 200k にしても、429 は消えない

https://learn.microsoft.com/ja-jp/azure/ai-services/openai/quotas-limits

# あとがき

最後に、ragas 関係のエラーまとめを書くかな・・

実はもう一個べつのエラーが出てるんですけどね・・・ :sweat_smile:
ChatGPT、GAS、Looker Studio、MagicPod Web APIでノーコード自動テストツールMagicPodの運用環境を構築した話

# ChatGPT、GAS、Looker Studio、MagicPod Web APIでノーコード自動テストツールMagicPodの運用環境を構築した話

## 概要
本記事では、ChatGPTを活用してMagicPodの運用効率を向上させるプロセスを紹介します。GAS（Google Apps Script）の特長である**サーバーレスでの自動実行**や、Looker Studio、MagicPod Web APIを組み合わせた運用環境の詳細、専用にカスタマイズしたGPTsの活用方法について解説します。

---

## 背景
MagicPodはノーコードでUIテストを作成できる強力なツールですが、以下の課題がありました：
- **古くなったバイナリの手動管理が手間**
- **ヘルススコアのモニタリングを効率化したい**
- **テストケースの管理や棚卸しを効率化したい**
- **ロケータの作成・分析に時間がかかる**

これらの課題を解決するために、ChatGPTを活用したカスタムGPTを作成し、それを基に運用環境の構築を行いました。

---

## カスタムGPTの役割
構築した運用環境では、以下のカスタムGPTを活用して各プロセスを効率化しました：

- **GAS Guru**  
![GAS Guru.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139865/e3cc2ca8-2957-b1dc-af7a-0b1b0a014829.png)  
  Google Apps Script（GAS）でスクリプトを自動生成するカスタムGPT。GASは、**サーバーやローカル端末を必要としない完全クラウドベースの実行環境**で、定期実行やAPI操作を簡単に自動化できます。この特長を活かし、効率的なスクリプトの作成と運用を支援します。箇条書き程度の仕様を入力するだけでスクリプトのドラフトを作成可能です。

<br>

- **Looker Studio Expert Bot**  
![Looker Studio Expert Bot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139865/fdd92f7e-d811-3132-be2e-258722dd24e2.png)  
  Looker Studioのダッシュボード作成をサポートするカスタムGPT。ダッシュボードを簡単に構築するための支援を行います。

<br>

- **Appiumで使うロケーターについてなんでも教えてくれるボット**  
![Appiumで使うロケーターについてなんでも教えてくれるボット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139865/6d34eb55-87c0-43c9-b2c2-41e3262526e2.png)  
  MagicPodで使用するロケータの作成や評価を支援するカスタムGPT。スクリーンショットやUIツリーを基に適切なロケータを提案します。

---

## 運用環境の構築プロセス

### 1. 古くなったバイナリの自動削除
- **使用GPT**: GAS Guru
- **使用API**: `DELETE delete-file`
- **概要**:  
  MagicPod上の古くなったバイナリを定期的に削除するプロセスを自動化。
- **プロセス**:  
  - カスタムGPT「GAS Guru」を活用してスクリプトを作成  
  - タイマーで毎日GASを実行  
  - 特定世代以上のバイナリを自動削除
- **ポイント**:  
  GASの特長である**サーバーレスでの自動実行**を活用し、管理コストを削減。サーバーやローカル端末を準備する必要がないため、設定後は完全にクラウド上で完結します。

---

### 2. ヘルススコアのSlack配信とモニタリング
- **使用GPT**: Looker Studio Expert Bot, GAS Guru
- **使用API**: `GET health-score`
- **概要**:  
  MagicPodのヘルススコアを取得し、ダッシュボードに可視化するプロセスを自動化。
- **プロセス**:  
  - GASでデータを取得し、Slackに配信  
  - カスタムGPT「Looker Studio Expert Bot」を活用してダッシュボードを作成
- **ダッシュボードの特徴**:  
  - トータルスコアと各項目の時系列データを表示  
  - スコア変動の要因を分析可能  
![Looker Studioダッシュボードの例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139865/7b2e4462-c109-4ca0-8f63-f50f99ab7cf7.png)  
*図1: Looker Studioを活用して作成したヘルススコアダッシュボード。時系列データに基づいてスコア変動に寄与した要因の分析が可能です。*

---

### 3. MagicPodのテストケース一覧作成
- **使用GPT**: GAS Guru
- **使用API**: `GET test-cases`
- **概要**:  
  テストケースの棚卸しやプラットフォーム間の比較に役立つ一覧を作成。
- **プロセス**:  
  - カスタムGPT「GAS Guru」を活用してスクリプトを作成  
  - 必要な情報を毎日取得し、Google Sheetsに出力

---

### 4. ロケータの分析・作成支援
- **使用GPT**: Appiumで使うロケーターについてなんでも教えてくれるボット
- **概要**:  
  ロケータに関連するエラーの特定や修正を効率化。
- **プロセス**:  
  - MagicPodの問い合わせフォームにあるスクリーンショット(png)とUIツリー(xml)をGPTに送信  
  - エラーの原因を特定し、適切なロケータを提案  
  - ロケータの評価や作成プロセスの学習も支援  
![ロケータ作成支援のUI例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139865/8ead31e6-5001-9371-9ec2-a5d754336894.png)  
*図2: ロケータ作成支援ツールのUI例。スクリーンショットをアップロードするだけでエラー原因を特定し、適切なロケータを提案します。*

---

## 今後の展望
MagicPod運用環境の自動化により、以下のメリットが得られました：
- **手動作業の削減による工数削減**
- **データドリブンな意思決定の強化**
- **学習コストの低減**
- **専用カスタムGPTによる自動化工数の大幅な削減**

これらのプロセスはさらに汎用化可能であり、他ツールへの応用も視野に入れています。

---
【Power Apps】SaaSによくある複数選択可能なテーブルの作り方

Power Appsではギャラリーやテーブルなど一覧表示を行うコントロールが用意されていますが、表示されているものを複数選択する機能を持つコントロールはありません。
(コンボボックスやモダンテーブルで複数選択は可能ですが、ユーザーライクではない)

この機能を実装することで、オブジェクト指向UIデザインに沿った一覧表示UIを作ることができるようになります。

## 1. ギャラリーの設定

キャンバスアプリ内にギャラリーコントロールを追加します。
ギャラリーのデータソースには、SharePointリストやDataverseなど、操作を行う対象のデータソースを指定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/f6921f44-7fb8-674f-12b5-6a2b1895cdfa.png)

## 2. チェックボックスの追加

ギャラリー内にチェックボックスを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/6093b314-3f35-33d8-c44a-607a22379b47.png)

以下のテキストをコピーしたうえで、右クリック→貼り付け→Paste codeでコントロールを貼り付けられます。

```
- CheckboxCanvas1:
    Control: CheckBox
    Properties:
      OnCheck: =Collect(ColCheck, ThisItem)
      OnSelect: =
      OnUncheck: =RemoveIf(ColCheck, ID = ThisItem.ID)
      Checked: =ThisItem.ID in ColCheck.ID
      Label: =""
      Height: =30
      Width: =38
```

OnCheckとOnUnCheckでそれぞれコレクションにThisItemを追加/削除しています。

また後述する全選択/全選択解除に対応できるように、Checked(デフォルトの選択状態)をコレクションに選択された値が含まれているかどうかに設定しています。
SharePointリスト以外のテーブル値の場合は、一意になるような列をinで比較してください。

## 3. 全選択・全非選択の実装

全選択・全非選択の機能を実装します。ギャラリー上部に以下のチェックボックスを設置してください。

```
- CheckboxCanvas1_1:
    Control: CheckBox
    Properties:
      OnCheck: =ClearCollect(ColCheck, Gallery1.AllItems)
      OnSelect: =
      OnUncheck: =RemoveIf(ColCheck, ID in Gallery1.AllItems.ID)
      Checked: =IsEmpty(ColCheck)
      Label: =""
      Height: =30
      Width: =38
      X: =30
      Y: =55
```

OnCheckではギャラリーに表示されているすべてのデータが選択され、OnUnCheckではその逆の操作が実行されます。

注意点としてこの数式のままだとギャラリーに表示されているデータ(既定で100件)しか操作されないので、すべてのデータを捜査対象とする場合は名前付き計算式を活用するなどの対応が必要になります。

## ヘッダーの設定など

ヘッダーを設定するなど、スタイルを調整しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/74873ed0-5369-d8da-99e2-73cc549e1f3b.png)

SharePointリストのリストビューやグリッドビューを参考にUI構築してください。

## 4. 選択されたデータの確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/4719f6e5-5e1c-a772-a8ca-0926dfc6ff76.png)

Gallery1をそのままコピーしてItemsプロパティをColCheckにすると、選択した結果を表示することができます。
表示が不要な場合は削除してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/7b1205da-ae20-e2ff-ff9b-a98b137841e3.png)

## 選択されたデータに対して操作を行う

選択されたデータに対して同じ処理を行う方法は以下の記事で紹介してます。

https://powerplatformnikki.com/multiprocess/

https://youtu.be/ZWl2jwC9p3w

https://youtu.be/FUVjkPnRsfg

RezaのナビゲーションバーやモダンツールバーのUIを参考にするとユーザーライクなSaaSっぽいUIになります。

## アップデート例

### 横スクロール可能にする

https://youtu.be/whbEjkuwxbo

https://youseibubu.com/apps/gallery_scroll

ヨウセイさんの横スクロール可能なギャラリーはよくマネします。

## 元記事

https://powerplatformnikki.com/multiselectgal/
【Unity】TimelineのカスタムMarkerを指定トラックのみ配置出来るようにする

本記事は、[Unity AdnventCalender 2024]("https://qiita.com/advent-calendar/2024/unity") の16日目の記事となります。
※枠が空いていたので代わりに投稿させていただく形となりました。12/25なのでギリギリセーフ。。。

# 概要
タイトルの通りですが、今回はUnityの機能の一つであるTimelineのMarkerの機能拡張の記事となります。そのため、Timeline, Markerに関しての基礎知識は既にある前提とします。

TimelineやMarkerに関する基礎知識・使い方に関しては、既に様々な方が良記事をネットで公開しているため、今回は省略します。

# MarkerはどのTrackでも置ける
TimelineでMarkerを使用する際には、以下のようなコードを書くと思います(INotification等は今回は省略)
```csharp:NormalMarker.cs
using UnityEngine.Timeline;

public class NormalMarker : Marker
{
}
```

上記のようなカスタムMarkerクラスを定義すると、TimelineWindowのサブメニューからトラック上にマーカーを設置できるようになります。
![marker0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332769/99e3bc97-87a3-3d46-49db-8cad864a160a.gif)

しかしこの方法だと、どのトラック上にもマーカーを設置することが出来てしまうため、場合によってはマーカーが散らばって意図しない挙動を起こす危険性もあります。

# カスタムMarkerを指定トラックのみ配置したい
本来ならば、指定したトラック上でのみサブメニューを開いた時のみ、「Add ○○ Marker」という項目を出現させるように出来れば良かったのですが、自分では良い方法を見つけられなかったので、今回は割とごり押し気味な方法で実装します。

以下が指定トラックのみ配置可能なカスタムMarkerクラスとなります
※今回はControlTrackを指定していますが、自分で作成したカスタムトラックでも問題ないです
```csharp:HogeMarker.cs
using UnityEngine;
using UnityEngine.Timeline;

public class HogeMarker : Marker
{
    public override void OnInitialize(TrackAsset aPent)
    {
        Debug.Log("Call OnInitialize");
#if UNITY_EDITOR
        // ControlTrackのみ配置できるようにする
        if (aPent is ControlTrack == false)
        {
            Debug.LogWarning($"このマーカーは{nameof(ControlTrack)}上のみ配置可能です");
            DestroyImmediate(this, true);
        }
#endif
    }
}
```

継承元のMarkerクラスには「OnInitialize(TrackAsset aPent)」という仮想関数が定義されており、ここでマーカーの初期化処理を上書きすることができます。この処理はマーカーの生成時にも呼ばれ、引数のTrackAssetにマーカーが配置されたTrackAssetの参照が入るので、ここで配置したいトラックの型かどうかを判定して、違う場合は即座に自分自身(生成したマーカー)を削除します。

上記で作成してHogeMarkerの挙動は以下の通りになります
![marker1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332769/5c2f7949-4aae-012a-99de-6c49e293fa78.gif)

## 余談：#if UNITY_EDITORで囲んでいる理由
※#if UNITY_EDITORで囲んでいる理由としては、このOnInitializeはTimelineのデシリアライズにも呼ばれるため、そのままにしておくとアプリ上でTimelineを再生する際に余計な処理不可となってしまうのを避けるためです。


# おわりに

かなり突発的に記事を書こうと思い立ったので、内容としては小ネタに近いですが何かの役に立てば幸いです。
また、他の方法やもっと良い手法等あれば、コメントで教えてもらえると有難いです。

# 検証環境
```
Windows 11
Unity 2022.3.22f1
Timeline 1.7.6
```

# 参考サイト

Class Marker
https://docs.unity3d.com/Packages/com.unity.timeline@1.8/api/UnityEngine.Timeline.Marker.html

Interface IMarker
https://docs.unity3d.com/Packages/com.unity.timeline@1.8/api/UnityEngine.Timeline.IMarker.html
【Power Apps編】開発補助ツールまとめ

これまで作成した開発を補助するための数式ジェネレーターやツールをまとめました。
随時更新中かつ不具合報告お待ちしております。

これらのツールは[v0](https://v0.dev/)で作成しています。テストしてある程度使えるレベルにしていますが、バグやエラーがあれば教えてください。
情報を抜き取るような機能はないですが、機密情報などの入力には注意してください。

## Text関数

Text関数の数式を選択形式で自動生成するツールです。

https://powerplatformnikki.com/text

## (作成中)Filter関数条件式ジェネレーター

あなたはギャラリーのItemsプロパティに数万行の数式が書かれているアプリを見たことがありますか？私はあります。
これはそんな悲劇を二度と繰り返さないためのツールです。

https://powerplatformnikki.com/text/filter

## ユーザー定義型自動生成ツール

使い方：
1. JSON関数の出力テキストを入力欄に貼り付ける
2. ユーザー定義型の名前を入力する(デフォルトはRootDef)
3. 「変換してコピー」ボタンを選択すると、結果がクリップボードにコピーされます
4. App.Formulasに貼り付ける

[ユーザー定義型自動生成ツールのコンポーネント]

https://powerplatformnikki.com/userdifinitiontool

## Power Automate編はこちら

https://powerplatformnikki.com/powerautomatesupporttool

### 元記事

https://powerplatformnikki.com/powerappssupporttool/
クリスマスです。Zip 爆弾をプレゼントしましょう。

:::note warn
なるべく心とPCのストレージに余裕のある友達にプレゼントしてあげてください。
:::

# 初めに
今日はクリスマスです。
つまり、この記事を読んでいるということは、あなたはきっと非リアでしょう。

嘘です。ごめんなさい。（あー!!戻るボタンなんてクリックしないで）

今日はクリスマスです。
プレゼントを用意しなくてはいけません。

というわけで、Zip 爆弾をプレゼントしましょう。

:::note info
**POINT**
以下の二つを心掛けましょう：
1. エンジニアらしいプレゼント
1. 爆発は芸術
:::

# 内容
:::note info
<details>
<summary>読まなくても...</summary>
+-

今年もあとちょっと。お仕事お疲れ様です。

メリークリスマス🎅🎉
</details>
:::

**Zip 爆弾** というものをご存知でしょうか？

**Zip 爆弾** とは...

小さなサイズの圧縮ファイルが展開されると膨大なサイズになる悪意のあるファイルです。

といったものです😊

:::note info
<details>
<summary>ちなみに...</summary>
+-

私はこんなふうにとらえています。

```diff_markdown
- 小さなサイズの圧縮ファイルが展開されると膨大なサイズになる悪意のあるファイルです。
+ 友達にプレゼントしたくなる小さいながらもとてもヤバい性能を発揮するステキなモノです。
```
</details>
:::



# コーディング
それではさっそく、プレゼントの作成に取り掛かりましょう。

今回は **十万回のループ処理** を行うため、処理速度が速いことで有名な C++ を使用してコーディングをさせていただきます。

非常に簡潔でありますが、以下は私が書かせていただいたコードです。

```c++
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main()
{
    // ファイルに記載する内容
    string filecontent = "メリークリスマス!";
    for (int c = 0; c < 666 * 4; c++) {
        filecontent += "メリークリスマス!";
    }

    // 00000.txt ~ 99999.txt のファイルを作成する
    for (int i = 0; i < 100000; i ++) {
        // ファイルの名前を決める
        string filename = to_string(i);
        while (filename.length() < 5) {
            filename = "0" + filename;
        }
        filename += ".txt";

        // ファイルを作成する
        ofstream MyFile(filename);
        MyFile << filecontent;
        MyFile.close();

        // コンソールに状態を出力
        cout << "Made " << filename << endl;
    }

    return 0;
}

```

:::note info
並列処理の実装もしていませんし、性能の悪いコードですので、改善して使っていただけるとよいと思います。
:::

**実行して** ...

処理に約15分かかりました。。。 **プレゼントを作るための努力** と考えれば苦でもないですよ！

さて、作成されたテキストファイルの容量は...

#### 6GB !
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674822/028018b1-3029-3ea7-4139-15add6e6c5b7.png)

まぁ、なかなかいいのではないでしょうか？

それでは、それを圧縮して Zip ファイルにしますと？

#### 44MB !
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674822/a7b64252-4736-d975-a733-e95be99fe230.png)

素晴らしい！
なんとも素晴らしい **Zip ファイル爆弾** が完成しました😀

# 最後に
この記事を投稿したら、作成したプレゼントを友達に渡そうと思います。
喜んでくれるといいな。

最後まで読んでくれてありがとう！
そして、メリークリスマス🍗

# 追記（ファイルの圧縮について）
:::note info
<details>
<summary>追記（これ）を追記した理由</summary>
+-

この記事を投稿した後に読んだら、 **エンジニアらしく** とか書いてるくせに **技術記事の匂いゼロ** だったので追記させていただきました。
</details>

:::

今回は、テキストファイルが入ったフォルダーを zip ファイルに圧縮して爆弾を製造しましたが、どのようにしてコンパクトに圧縮されたのかという話です。

圧縮した zip ファイルは、 **[Explzh](https://www.ponsoftware.com/)** というソフトで、以下の写真のように詳細が確認できます。（このソフトは windows のみ対応です。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674822/2e8c856b-15c2-b3f4-e00e-57a259eed563.png)

<details>
<summary>読まなくていいセリフ</summary>
圧縮率 1% 未満って...理想の消費税といったところでしょうか😆
</details>

[圧縮方法] に記載されている ``Deflate`` については、以下の二つの Wikipedia の document を参照していただければ理解できると思います。ちなみに私はファイルの圧縮がどのように行われているのか具体的な手法を知らなかったのでいい勉強になりました。
- [Deflate について](https://ja.wikipedia.org/wiki/Deflate)
- [ハフマン富豪について](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%95%E3%83%9E%E3%83%B3%E7%AC%A6%E5%8F%B7)
Flutterのチュートリアルを学んでみた(7)

# Containerウィジェットをマスターしよう！ 📦

## Containerってなに？ 🤔

Containerは、中身を自由にカスタマイズできる箱のようなものです！
例えば：
- 大きさを変える
- 色を付ける
- 余白を作る
- 中身の位置を調整する

など、いろんなことができます！

## 基本の形 📝

まずは、青い四角を作ってみましょう：

```dart
Container(
  color: Colors.blue,    // 青色に塗る
  width: 300.0,         // 幅300
  height: 300.0,        // 高さ300
)
```

## 色の付け方 🎨

### 方法1：Colorsクラスを使う（簡単！）
```dart
Container(
  color: Colors.blue,      // 基本の青
  // color: Colors.green,  // 緑
  // color: Colors.red,    // 赤
)
```

色の濃さも変えられます：
```dart
Container(
  color: Colors.blue[900],      // とても濃い青
  // color: Colors.blue[100],   // とても薄い青
)
```

使える数値：50, 100, 200, 300, 400, 500, 600, 700, 800, 900

### 方法2：自分で色を作る（難しいけど自由！）
```dart
Container(
  color: Color(0xFF42A5F5),                    // 16進数で指定
  // color: Color.fromRGBO(66, 165, 245, 1.0), // RGBで指定
)
```

## 文字を入れてみよう 📝

```dart
Container(
  color: Colors.blue,
  width: 300.0,
  height: 300.0,
  child: Text('こんにちは！'),  // この行を追加！
)
```

## 余白を付けよう 📏

### 内側の余白（Padding）
```dart
Container(
  color: Colors.blue,
  width: 300.0,
  height: 300.0,
  child: Text('こんにちは！'),
  padding: EdgeInsets.all(50.0),  // 全方向に50の余白
)
```

特定の方向だけ余白を付けたい場合：
```dart
padding: EdgeInsets.only(
  top: 50.0,    // 上だけ
  left: 20.0,   // 左だけ
)
```

### 外側の余白（Margin）
```dart
Container(
  color: Colors.blue,
  width: 300.0,
  height: 300.0,
  child: Text('こんにちは！'),
  margin: EdgeInsets.all(100.0),  // 外側に余白
)
```

## 中身の位置を調整しよう 🎯

```dart
Container(
  color: Colors.blue,
  width: 300.0,
  height: 300.0,
  child: Text('こんにちは！'),
  alignment: Alignment.center,  // 真ん中に配置
)
```

使える位置：
- 上：topLeft, topCenter, topRight
- 真ん中：centerLeft, center, centerRight
- 下：bottomLeft, bottomCenter, bottomRight

## 形を変えてみよう 🔄

回転させる：
```dart
Container(
  color: Colors.blue,
  width: 300.0,
  height: 300.0,
  child: Text('こんにちは！'),
  transform: Matrix4.rotationZ(0.1),  // 少し傾ける
)
```

## やってみよう！ 🌟

1. 違う色を試してみる
```dart
Container(
  color: Colors.purple,  // 紫にしてみる
)
```

2. 大きさを変えてみる
```dart
Container(
  width: 200.0,   // もっと小さく
  height: 100.0,  // 横長に
)
```

3. 余白を組み合わせてみる
```dart
Container(
  padding: EdgeInsets.all(20.0),
  margin: EdgeInsets.only(top: 50.0),
)
```

## 困ったときは？ 🆘

- 色が反映されない
  → colorプロパティのスペルを確認
- 大きさが変わらない
  → widthとheightの単位（.0）を確認
- 位置がおかしい
  → alignmentの値を確認

## 次は何ができる？ 🎯

- 複数のContainerを組み合わせる
- 角を丸くする
- 影を付ける
- アニメーションを付ける

## チャレンジ問題 💪

1. 赤い箱の中に青い文字を表示してみよう
2. 箱を少し傾けて、余白も付けてみよう
3. 自分の好きな色の組み合わせで箱を作ってみよう

がんばって練習してみましょう！
Containerをマスターすれば、もっと素敵なアプリが作れますよ！ 🎨
R6秋　応用情報午後　プログラミングを検証

# いざ、検証！
```prime1(20),prime2(20),prime3(20)```をそれぞれ実行したときの```L1,L2,L3```の実行回数を検証します。

# コード
```C:r6a.c
#include <stdio.h>

int L1 = 0;
int L2 = 0;
int L3 = 0;

int* prime1(int N, int primes[], int* count){
    int i = 0;  // primesの末尾インデックス
    int isPrime; // 1:True(prime), 0:False(not prime)

    int d = 2;
    int t;
    while(d <= N){
        isPrime = 1; // True, 素数と仮定
        t = 2;
        while(t < d){
            if(d % t == 0){
                isPrime = 0; // False
            }
            t++; // <---------------------(L1)
            L1++;
        }
        if(isPrime == 1){
            primes[i++] = d;
        }
        d++;
    }

    *count = i;  // 素数の個数をカウント
    return primes;
}

int* prime2(int N, int primes[], int* count){
    int i = 0;  // primesの末尾インデックス
    int isPrime[21] = {0};

    int c = 2;
    int d = 2;
    int t;
    while(c <= N){
        isPrime[c] = 1;
        c++;
    }
    while(d <= N){
        if(isPrime[d] == 1){
            primes[i++] = d;
            t = d * d;
            while(t <= N){
                isPrime[t] = 0;
                t += d; // <---------------------(L2)
                L2++;
            }
        }
        d++;
    }

    *count = i;  // 素数の個数をカウント
    return primes;
}

int* prime3(int N, int primes[], int* count){
    int i = 0;  // primesの末尾インデックス
    primes[i++] = 2; // 素数2を格納
    int isPrime[21] = {0};

    int c = 3;
    int cindex = 1;
    int d = 3;
    int t;
    while(c <= N){
        isPrime[cindex++] = 1;
        c += 2;
    }
    while(d <= N){
        if(isPrime[(d-1)/2] == 1){
            primes[i++] = d;
            t = d * d;
            while(t <= N){
                isPrime[(t-1)/2] = 0;
                t += 2 * d; // <---------------------(L3)
                L3++;
            }
        }
        d += 2;
    }

    *count = i;  // 素数の個数をカウント
    return primes;
}

int main() {
    int N = 20;
    int primes[N];
    int count;
    
    int* prime_list1 = prime1(N, primes, &count);
    int* prime_list2 = prime2(N, primes, &count);
    int* prime_list3 = prime3(N, primes, &count);

    printf("%d, %d, %d\n", L1, L2, L3);
    return 0;
}
```
実行結果
```
171, 13, 2
```

# 時間計測（ナノ秒）
ヘッダーファイルをインクルードして
```C
#include <time.h>
```
main関数を以下に書き換えて実行。なお、実行時間はマイクロ秒以下のため、time()やclock()だと0になってしまう。
```C
int main() {
    int N = 20;
    int primes[N];
    int count;
    struct timespec start, end;
    
    timespec_get(&start, TIME_UTC);
    int* prime_list1 = prime1(N, primes, &count);
    timespec_get(&end, TIME_UTC);
    printf("prime1:%ld\n", end.tv_nsec - start.tv_nsec);
    
    timespec_get(&start, TIME_UTC);
    int* prime_list2 = prime2(N, primes, &count);
    timespec_get(&end, TIME_UTC);
    printf("prime2:%ld\n", end.tv_nsec - start.tv_nsec);
    
    timespec_get(&start, TIME_UTC);
    int* prime_list3 = prime3(N, primes, &count);
    timespec_get(&end, TIME_UTC);
    printf("prime3:%ld\n", end.tv_nsec - start.tv_nsec);

    return 0;
}
```
出力結果 (paiza.io)
```
prime1:392
prime2:128
prime3:30
```
もちろん、実行ごとに値は変わるが、だいたいこんな感じになった。
N = 100とかにすると、```Bus error (core dumped)```となってしまった。
本当は大きい数で試すほうが正確ではある。
ragas で またでた "output": prompt_trace.outputs.get("output", {})[0] は、library の問題っぽかったので、0.2.8 ⇒0.2.9 とした

# 背景

解決したかと思っていたこの問題・・また発生したので、その対処記録

https://qiita.com/baku2san/items/d26e4c58b99666ae2943

# 結論

library を バージョン指定してなかったので、最新版を指定して update

```diff: update requirements.in
- ragas
+ ragas==0.2.9
```

```diff: update requirements.txt
- ragas==0.2.8
+ ragas==0.2.9
```

# 経緯

debug を有効化してみてみたけれど、何もエラーが無い
にも拘らず発生したので、update してみたら直った。

# あとがき

とはいえ・・子のバージョンでの変更点は確認してないので・・何とも確証がない・・ :sweat:
【Python】プログラミング初学者におすすめの Udemy の講座 

プログラミング初学者におすすめする `Python` 講座を紹介します。


https://www.udemy.com/course/python-beginner/

こちらの Udemy の講座は、私がプログラミングを本格的に学習し始めた際に最初に触れた教材で、今でもよく見返しています。


# 講座の特徴

1. **初心者向けの丁寧な解説**
   変数、データ型、条件分岐、ループといった基礎的な部分から始まり、Pythonの基本構文をしっかりと学べます。
  初めてプログラミングに触れる方でも無理なく進められる構成になっています。
2. **実践的な応用技術**
   基本を学んだ後は、ファイル操作、Web APIの使用、データ解析といった実践的な課題に進みます。
   実際の現場で役立つ知識とスキルを身につけることができます。
3. **コードスタイル**
   Python のコーディング規約（PEP 8）に則った、読みやすく保守性の高いコードを書くスキルが身につきます。

# 講座の内容

この講座は、プログラミング初心者の方でも安心して学べるよう、「**入門編**」と、さらにスキルアップを目指す方のための「**応用編**」の 2 つに内容が分かれています。

**入門編**では、プログラミングの基礎を体系的に学ぶことができ、自信を持って次のステップへ進むことができます。プログラミング初学者は入門編だけでも十分です。

入門編の終わりに、アプリケーションを実装する**演習**があります。最初は難しく感じるかもしれませんが、入門編を見返すことで着実に力がつき、演習を実装できるようになります。

**応用編**では、マルチスレッド、マルチプロセス、非同期処理など、実践的な開発でよく利用されるテーマをわかりやすく解説しており、**日々のプログラミングで困ったときに役立つ情報が満載**です。
【Unity】AssetのAnimationの座標がずれて困った話

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

AssetStoreで購入したGrruzam Powerful Sword Animation(Great Sword, Katana)のAnimationで座標ずれを直すのに少し時間がかかったので、メモ書きを残して置きます。

https://assetstore.unity.com/packages/3d/animations/powerful-sword-pack-great-sword-katana-183324?srsltid=AfmBOorDXk2kTWdi0c0xztmaYM-F6lVI3_u5itWgzPSRLQioeqBEMt11

# 結論
BakeIntoPoseの設定をoffにしたら、座標が固定されるようになった。

# やったこと
19日目の記事で書いた対処方は一通りやりました。

・ApplyRootMotionのチェックを外す
・BakeIntoPoseのチェックをつける(最初からついていた)

今まで、これらのことをやっていると大体できたことが多かったのですが今回は直りませんでした。

Animationの座標に問題があるのかと考え、座標を全部消したらAnimationが変な風になりましたね(それはそう)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/41a58c20-18b1-8de1-3473-d65676ab1add.png)

# そして解決
ふと、BakeIntoPoseを外したらどうなるんだろう...?と思い外すと解決しました。

そもそもBakeIntoPoseについて全然理解していなくて、公式リファレンスを覗いてみました。

>BakeIntoPose
垂直方向のルートモーションをボーンの動きにベイクします。ルートモーションとして保存する場合は無効にします。
>
>水平方向のルートモーションをボーンの動きにベイクします。ルートモーションとして保存する場合は無効にします。

全然分からない...ぞ？？？？

色々調べたところ、元座標が動かず、Animationでキャラクターが動くかどうかという設定なのかな....

https://knb-mayumi.com/unity-rootmotion/

<iframe width="560" height="315" src="https://www.youtube.com/embed/3BBNeKCPFIM?si=ArUoELqUF7H7cefO&amp;start=126" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

# 2025/1/21追記
Grruzam Powerful Sword Animation(Great Sword, Katana)の座標固定方法がはっきりと分かったので追記文です。Grunzam...と書くと長いのでAssetのアニメ~~やアニメーションとかで単語を書いています。

まず、Assetsのアニメーションは通常バージョンとInplaceと書かれている物があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/ef2abeb8-0035-0f23-763f-855a153111fd.png)
※ IdleやMoveなど一部のアニメーションにはInplaceが無いので注意

Inplaceという単語を翻訳すると置くや、その場でという意味になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/a884798d-91b7-eedd-2122-11d36127a25c.png)

つまり、Inplaceと書かれているクリップを選択すれば座標が動かないという分けですね。

これで座標が固定される！と思ってAnimationの仮再生を見ると...**ずれているんですよね...座標が...**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/9a790ce9-d5f9-efcb-58e5-300fe8b37129.png)


という訳で、ここからが本題。今から設定を変更してアニメーションの座標を固定します。利用するアニメーションクリップは何でもいいです。設定は簡単で、

・Root Transform RotationとRoot Transform Position(Y),(XZ)のBake Into Poseにチェックを入れる
・Based UponをOriginalに直す
この2つに設定することで座標を固定することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/acadb1d0-b27c-5da5-42b7-04ecd877a4b9.png)

さっきと見比べても、キャラクターの位置が変わらない状態になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/fce69b8e-9329-0b96-eadd-0892afd09076.png)
あなたへのエール｜文章題で身に付くプログラミング思考入門️（25/25）

## はじめに

『文章題で身に付くプログラミング思考入門️』は、日常や文章問題からプログラミング思考を身に付けていく、簡単で身近で、あなたをちょっと輝かせてくれるシリーズです。

最終回の今回は、あなたへのエールとこれまでの振り返りで締めたいと思います。

## あなたへのエール

AIがどんどん進化してきて、仕事が奪われるんじゃないかと不安になったことはありますか？
才能や能力や経験あふれる新人が入ってきて、自分の価値を信じられなくなったことはありますか？

大丈夫です。あなたにしかできないことが、必ずあります。
それを見つけるのは、あなたです。

その上で大切なことは、柔軟、理念、責任です。

- 柔軟
    - 相手の出方に応じて対応できる柔軟さは、あなたの力の証明です。
- 理念
    - 社会のために、人のために、自分のために、どうあるべきか。問い続ける謙虚さが、あなたを成長させてくれます。
- 責任
    - 責任を取る側になりましょう。AIは責任を取れません。使う側が、責任を取れる側です。人間だけが責任を取れます。あなたのリーダーは、あなたです。

またどこかでお会いしましょう！

## 振り返り

https://qiita.com/advent-calendar/2024/thewaggle

Qiita Advent Calendar 2024 科学・理論部門の第1位でした！（2025/12/25時点）

読んでいただき、貴重な機会をいただき、誠にありがとうございました。
![スクリーンショット 2024-12-25 20.51.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147743/5d1384ef-37c2-81d9-bbbb-d94e403723fe.png)
【AWS】問答無用でEC2をすべて停止させる方法

# 発端
使わないEC2を日次で停止させておきたい。ただ、タグをいちいち指定するのもめんどくさいから、問答無用でアカウント内の全EC2を停止させたい。
停止させる方法をぐぐってみたが、意外と出てこない


# やりたい事（要件）
* タグを指定しないで全EC2を停止させる
* 起動はさせない
* EventBridgeSchedulerを使ってトリガーさせる
* 簡単に実装したい

# EC2を停止させる方法
EC2を指定させる方法を列挙します。
* SSM Automation
* Lambda
* SSM Resource Scheduler
* AWS Instance Scheduler

# 要件に合うものは・・・
* SSM Automation
→　できそう。
* Lambda
→　コードを実装するのが面倒だができそう。
* SSM Resource Scheduler
→　起動がセットになってるのでダメ。（自動起動はしたくない）
* AWS Instance Scheduler
→　同上

# 結局選んだのは
結果的にLambdaで実装しました。理由としてはLambdaで実装すると結構スリムに作れる＆Lambdaのコンソールからトリガー、ロールにアクセスできるので管理が楽そうだったからです。
コードの実装に関してはChatGPTにお願いすると一瞬で出力してくれました。ﾅﾆﾄｿﾞﾅﾆﾄｿﾞ

# 実装

### １．Lambda関数の作成
以下のソースコードでLambda関数を作成しました。
ランタイムはPython3.13です。作成後に**タイムアウト時間を1分に変更してください。**
デフォルトの3秒のままだと実行がタイムアウトして停止が実行されませんでした。
```python:lambda_function.py
import boto3
 
def lambda_handler(event, context):
    # EC2クライアントを作成
    ec2 = boto3.client('ec2')
 
    all_instance_ids = []
    instance_id = ""
    try:
        # 停止したいインスタンスのIDを指定
        response = ec2.describe_instances()
       
        # reservationsからInstancesリストを取り出す
        instances_list = response.get('Reservations', [])
        for reservation in instances_list:
            for instance in reservation.get('Instances', []):
                instance_id = instance.get('InstanceId')
                # インスタンスを停止
                response = ec2.stop_instances(InstanceIds=[instance_id])
                print(f"Stopping EC2 instance: {instance_id}")
                print(f"Response: {response}")
 
        return {
            'statusCode': 200,
            'body': f'Successfully initiated stop for instance'
        }
 
    except Exception as e:
        print(f"Error stopping instance {instance_id}: {str(e)}")
        return {
            'statusCode': 500,
            'body': f'Error stopping instance {instance_id}: {str(e)}'
        }
```
### ２．実行ロールの変更
作成された実行ロールのままではEC2を停止させるポリシーが不足しているので、対応したポリシーを追加します。
具体的にはLambdaの実行ロールに対して以下のポリシーを追加しました。

```json:ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "StopEC2InMyAccount",
            "Effect": "Allow",
            "Action": "ec2:StopInstances",
            "Resource": "arn:aws:ec2:*:<アカウントID>:instance/*"
        },
        {
            "Sid": "ListUpEC2InstanceID",
            "Effect": "Allow",
            "Action": "ec2:DescribeInstances",
            "Resource": "*"
        }
    ]
}
```
### ３．トリガーの追加
Lambdaコンソールからトリガーを追加します。
こんな感じで作りました。毎日の21:00JSTにトリガーが起動する設定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683704/cff69bd0-3d3d-4f07-4515-36acf215f9b5.png)

# まとめ
現在存在している方法が大体インスタンスのタグを指定するか直接インスタンスIDを指定して停止させる方法ばかりなので、Lambdaでの方法が一番シンプルに作成できるのではないかと思います。
もっといい方法があったらコメントをお願いします！
Flutterのチュートリアルを学んでみた(6)

# Flutterのレイアウトを学ぼう！基礎編 🎨

## はじめに 👋

レゴブロックで遊んだことありますか？
Flutterのレイアウトは、レゴブロックを組み立てるようなものです。
小さなパーツ（Widget）を組み合わせて、素敵なアプリを作っていきます！

## Widgetって何だろう？ 🧩

Flutterでは、画面に表示する全てのものを「Widget」と呼びます：
- 文字 → Textウィジェット
- 画像 → Imageウィジェット
- ボタン → Buttonウィジェット
- 箱 → Containerウィジェット

## レイアウトの基本パーツを見てみよう！ 📦

### 1. Container（箱）ウィジェット 📦

Containerは、中に物を入れられる箱のようなものです：

```dart
Container(
  padding: EdgeInsets.all(8.0),  // 内側の余白
  margin: EdgeInsets.all(8.0),   // 外側の余白
  color: Colors.blue,            // 背景色
  child: Text('こんにちは！'),    // 中身
)
```

できること：
- 余白をつける（padding, margin）
- 色を付ける（color）
- 枠線をつける（border）
- 角を丸くする（borderRadius）

### 2. Row（横並び）とColumn（縦並び）🎯

#### Row（横並び）
```dart
Row(
  children: [
    Icon(Icons.star),
    Text('星'),
    Icon(Icons.moon),
    Text('月'),
  ],
)
```

#### Column（縦並び）
```dart
Column(
  children: [
    Icon(Icons.sun),
    Text('太陽'),
    Icon(Icons.cloud),
    Text('雲'),
  ],
)
```

### 3. レイアウトを見やすくする方法 🔍

デバッグモードを使うと、レイアウトが見やすくなります：

```dart
import 'package:flutter/rendering.dart';

void main() {
  debugPaintSizeEnabled = true;  // これを追加！
  runApp(MyApp());
}
```

これで、こんなことが見えるようになります：
- ウィジェットの範囲
- 余白の大きさ
- 位置関係

## マテリアルデザインを使ってみよう 🎨

### 簡単な方法（おすすめ）
```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '私のアプリ',
      home: Scaffold(
        appBar: AppBar(
          title: Text('かわいいアプリ'),
        ),
        body: Center(
          child: Text('こんにちは！'),
        ),
      ),
    );
  }
}
```

### 自由な方法（上級者向け）
```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(color: Colors.white),
      child: Center(
        child: Text(
          'こんにちは！',
          textDirection: TextDirection.ltr,
          style: TextStyle(
            fontSize: 32,
            color: Colors.black,
          ),
        ),
      ),
    );
  }
}
```

## やってみよう！ 🌟

1. Containerの色を変えてみる
```dart
Container(
  color: Colors.pink,  // 好きな色に変えてみよう！
  child: Text('ピンクの箱'),
)
```

2. 横並びと縦並びを組み合わせる
```dart
Column(
  children: [
    Row(
      children: [
        Icon(Icons.star),
        Text('星'),
      ],
    ),
    Row(
      children: [
        Icon(Icons.moon),
        Text('月'),
      ],
    ),
  ],
)
```

## 大切なポイント ⭐️

1. Containerは便利な箱
2. Rowは横並び、Columnは縦並び
3. MaterialAppを使うと簡単にきれいなデザインができる
4. debugPaintSizeEnabledで構造が見やすくなる

## 次は何ができる？ 🎯

- 複雑なレイアウトを作る
- アニメーションをつける
- タップできる要素を追加する
- スクロールできるリストを作る

## 実験してみよう！ 🔬

1. 違う色を試してみる
2. 余白の大きさを変えてみる
3. テキストとアイコンを組み合わせてみる

## 困ったときは？ 🆘

- 位置がおかしい
  → debugPaintSizeEnabledで確認
- 文字が表示されない
  → TextStyleを確認
- レイアウトが崩れる
  → Containerで囲んでみる

がんばってレイアウトの練習をしましょう！
あなたなら素敵なアプリが作れるはず！ 💪
baserCMS 5系で使えるエイリアスを使った小ネタ

[baserCMS](https://basercms.net/ "baserCMS公式サイト")は、ブログなどに別のURLやレイアウトをあてがう「エイリアス」機能があります。
ブログを複数設置できるbaserCMSではあまり使用する機会は少ないかもしれませんが、サブサイトなどでエイリアスを使って本体サイトのブログを呼び出して使用したりする際に、サブサイトのレイアウトを使用したいときなどに使える機能です。
ただし、そのままだと記事へのリンクなどが元のブログのURLに変わってしまうため、少し工夫が必要になります。
ここでは、それらの問題を解消するちょっとした小ネタを紹介します。

:::note warn
この記事は、以下の環境で動作確認を行っております。
baserCMS version 5.0.11
:::

## ブログエイリアスのindexページの記事へのリンク
```$this->Blog->getPostLinkUrl($post)```
で、リンクURLが元のURLに戻ってしまうときは
index.phpのループの前に下記の記述をつけると現在いるコンテンツがセットされて、エイリアスの場合はエイリアスのURLで記事のリンクが出力されます。

```
$currentContent = $this->BcBaser->getCurrentContent();
// エイリアスの場合、エイリアスのコンテンツをURLにセット
//（$this->Blog->currentContentで、元のBlogContentがセットされてしまいリンクが元URLに戻ってしまうため）
if (!empty($currentContent->alias_id)) {
  $this->Blog->currentContent = $currentContent;
}
```

## blogPosts
```$this->BcBaser->blogPosts($blogname);```
では、エイリアスを呼び出せないため
呼び出した先のブログ記事などのURLをエイリアスに変更したいときは
```
$contntUrl = {エイリアスのURL};
$contentTable = \Cake\ORM\TableRegistry::getTableLocator()->get('BaserCore.Contents');
$content = $contentTable->find()->where([
    'Contents.url' => $contntUrl,
    'Contents.type' => 'BlogContent',
    'Contents.alias_id IS NOT' => null,
])->first();
if(!empty($content)) $this->Blog->currentContent = $content
```
これで
```$this->Blog->getPostLinkUrl($post)```
などのリンクURLがエイリアスのものに変わります。

:::note info
ポイント
```$this->Blog->currentContent = $XXXXXXXX;```
でブログコンテンツの情報を変更できるので、色々試してみるのも面白いです。
:::


## 年別アーカイブなど
```/templates/element/blog_yearly_archives.php```
をエイリアスでも共通で使用している時、
年別のURLが元のブログへのURLとなってしまうため
```
if (empty($currentContent)) $currentContent = $this->BcBaser->getCurrentContent();
```
でcurrentContentを取得して
リンクURLを
```
$this->BcBaser->getBlogContentsUrl($id) . 'archives/date/' . $postedDate['year']
```
↓↓
```
$currentContent->url . 'archives/date/' . $postedDate['year']
```
にしてやると元のBlogとエイリアスのどちらでもそれぞれのコンテンツのURLになります。

:::note info
ポイント
```$this->BcBaser->getCurrentContent();```
でベースとなるURLをしっかり指定する。
:::

エイリアスも使っていくとなかなか面白い機能なので、どんどん使っていきましょう。

:::note warn
注意
一部情報が古くなっている場合がございます。
その場合は、ご指摘ください。
:::