OmniAICreator/Qiita-1.07M huggingface dataset:
データ基盤学習必見　クラウドデータレイク（OREILLY出版）早速読んでみた　2024/5/17

# 1.前置き

みなさんこんにちは、私は日頃データ基盤の構築を行なっております。

近年、オライリー者からデータ基盤の本が多数出てきていること、本当に嬉しく思います。

さて、２０２４年５月１７日にそのオライリー社から新たに
クラウドデータレイクという本が出版されました

今回はその本の感想をしていきたいと思います。

https://www.oreilly.co.jp/books/9784814400676/

解説は思ったのですが、内容がかなり網羅的に記載されている分、記事にすると余計抽象的になってしまい記事の内容を考え中です。

# 2.まずはこの本の感想

## 現場のエンジニアにとってはちょっと浅いと感じるかもしれない。

これが一番の感想でした。
この本の本当のターゲットは恐らく、
『これからデータ基盤を構築したいけど、概略もよくわからない』
『データレイクってなに？』
『なんでデータレイクにデータを入れる必要があるの？』
これがあまり理解できていない方に対しての本なのかなと思います。

また、最近機械学習などの流行から
『データレイクハウス』
という言葉が出てきていると思います。

それらの説明をわかりやすくしています。

## 経営者に読んでほしい理由

なぜか
・コスト面もかなり多く記載されている（第２章・第３章）
・PaaS製品の各々の強みや特徴が凝縮されている（第２章・第４章）
・このような質問に対して、どの解答であればデータレイクが重要となるか（第７章）

いざデータ基盤を構築しようとなると、
ユーザーのニーズを除いて、やはりサービスの選定が大事になってくるかと思います。

それらの手助けとなるものが簡潔に記載されています。
また、それぞれのアーキテクチャのコスト面の比較などもしています。

## データ基盤の初学車にも読んでほしい
なぜか
・HadoopやSparkなどのコンポーネント等の簡易説明（第４章）
・データの圧縮に関係するparquetフォーマットの説明（第５章）

エンジニアが読むべき章は恐らく第４章と第５章と第６章かなと思います。


## 章ごとに対象者を選定してみた
この本自体は、第１章から第８章で構成されています。
ざっと章ごとに対象者に丸をつけました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2526914/e7eb7dba-b738-3dca-a33a-f42de47f0fe1.png)

まるはつけましたが、
現場のエンジニアが経営者側の視点を持つことも非常に大事だと思います。

将来 PMとしてキャリアチェンジしたい方は是非全部読んでください


# 3.まとめ　データ基盤の概要を掴むにはこれ一本でいいかも

それくらいかなり網羅的に記載されています。
デメリットとしては、網羅的すぎてあまり深いところまでは記載されていないことです。

なので、これからデータ基盤を勉強したい！って方には読んでいただきたいと思います。

https://www.oreilly.co.jp/books/9784814400676/
カイ二乗(x2:chi squared)

カイ二乗($\chi^2$:chi squared)

・観測度数が期待度数からどれくらい離れているかを計算した値
・{(観測度数-期待度数)^2 / 期待度数}の総和

"どれくらい離れているか"を調べるには観測度数と期待度数の差を計算すればよさそうですね。ですがただ単に差をとって足し合わせると、プラスとマイナスで打ち消し合ってゼロになってしまいます。
そこで、二乗した総和にしてみましょう。(絶対値だとマイナスを掛けないといけないため、扱いにくい!)


![カイ二乗.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780659/2143d056-3dde-94e5-76ef-bf8c617d6314.png)

数式で書くと以下のようになります。
a行b列の分割表におけるi行j列の観測度数がnij，期待度数がeijとすると
```math
\chi^2 = \sum^a_{i=1}\sum^b_{j=1}\frac{(n_{ij}-e_{ij})^2}{e_{ij}}
```



## 連関(association)

**Pythonで実践**
分割表を求める
・pd.crosstab(xarray, yarray)


```
import pandas as pd

# データ準備
df = sns.load_dataset('tips')
df['tip_rate'] = df['tip'] / df['total_bill']

pd.crosstab(df['sex'], df['time'])
```
![スクリーンショット 2024-05-18 10.16.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780659/d3a9c9a9-44d5-eecf-8142-9ade037475dc.png)

$\chi^2$と期待度数を求める
・stats.chi2_contingency(cont_table, correction=False)

```
from scipy import stats


cont_table = pd.crosstab(df['sex'], df['time'])
stats.chi2_contingency(cont_table, correction=False)
```
結果

(10.277251918677742,　　  　　　　　第1戻り値 -> $\chi^2$
 0.0013468039268008766,
 1,
 array([[ 43.75409836, 113.24590164],
        [ 24.24590164,  62.75409836]]))　　　第4戻り値 -> 期待度数


---
この結果の$\chi^2$を見ても大きいのか小さいのかわからないのですよね。
次回は、相関係数で学習したときと同様に標準化することを考えます。
[React] Reactでのスタイル指定はどうするの？

### 概要
Reactでのスタイル適用方法についてまとめました。

---

### ソリューション
ReactでCSSを用いる場合、基本的には以下いずれかの対応となります。
- インラインスタイル
- cssインポート
- CSS Modules
- CSS-In-JS
- CSSフレームワークの導入

早速見ていきましょう。

---

### インラインスタイル
名前の通り、インラインスタイルとしてJSXにスタイルを適用する手法です。
`style`属性に、オブジェクトとして定義したスタイルを指定します。

```tsx
<div style={{ color: 'red' }}>赤色</div>
```

#### :memo: スタイルオブジェクトについて
`style`として定義したオブジェクトは`React.CSSProperties`というデータ型になります。
プロパティの検証/補完をしてくれるので、オブジェクトを切り離して宣言する場合は、明示的に型指定するようにしましょう。

```tsx
const styledDivColor :React.CSSProperties = {
  color: 'red'
}

<div style={styledDivColor}>赤色</div>
```

#### メリットとデメリット
- メリット
    - 簡単にスタイル定義ができる
- デメリット
    - メディアクエリや擬似要素が利用できない
    - スタイル再利用ができない

---

### CSVインポート
外部ファイルとして定義したCSSをコンポーネントでインポートする手法です。

`1. CSSファイルの作成
```css
/* sample-import.css */
.color-red-component {
  color: red;
}
```

`2. 作成したCSSをコンポーネントでインポート
```tsx
// SampleImportCsv.tsx
import './sample-import.css';

const SampleImportCsv = () => {
  return (
    <>
      <div className="color-red-component">赤色コンポーネント</div>
    </>
  );
};

export default SampleImportCsv;
```

#### メリットとデメリット
- メリット
    - スタイルの再利用が可能
- デメリット
    - スタイルの適用範囲はインポートしたコンポーネントだけでなく、**アプリケーション全体**となる
    - `app.css` など全体に適用したいスタイルはこの方法を用いる

---

### CSS Modules
CSSクラス名がグローバルスコープではなく、ローカルスコープで定義されるようにする技術です。
前述のCSSがグローバルスコープで適用されてしまう問題を解決することができます。

`1. **.module.css** の形式でCSSを作成します。
```css
/* sample.module.css */
.title {
  color: red;
}
```

`2. コンポーネントdmoduleをインポートし、スタイル適用したい要素のクラス名に対応するクラス名を指定します。
```tsx
// SampleComponent.tsx
import styles from './sample.module.css';

const SampleComponent: FC = () => {
  return <h1 className={styles.title}>Hello!</h1>
}
```

`3. 一意のクラス名が割り当てられ、対応するスタイルが適用されます。
```html
<h1 class="_title_11mo7_1">Hello!</h1>
```

---

### CSS-In-JS
JSファイルの中にCSSを記載する手法。
`styled-components` や `emotion`などの、ライブラリを用いる。

#### サンプルコード
```tsx
import styled from 'styled-components';

const PickUpButton = styled.button`
  background-color: #007bff;
  color: white;
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 16px;
  transition: background-color 0.3s;

  &:hover {
    background-color: #0056b3;
  }
`;

const SampleImportCssInJs = () => {
  return (
    <div>
      <PickUpButton>Click Me</PickUpButton>
    </div>
  );
};

export default SampleImportCssInJs;
```

#### 生成されるHTML
ランダムなクラスが指定されます。
これにより、独立したコンポーネントにのみスタイルを適用することが可能です。

```html
<button class="sc-eqUzNf iIlGPi">Click Me</button>
```

#### 動的なスタイルの指定
コンポーネントに渡されたプロパティを基にスタイルを動的に指定することも可能です。

```tsx
import styled from 'styled-components';

interface Props {
  width: number;
  height: number;
}

const Icon = styled.img<Props>`
  width: ${(props) => props.width}px;
  height: ${(props) => props.height}px;
`;

const image_path = 'path/to/image.jpg';
const width = 50;
const height = 50;

<Icon src={image_path} alt="profile" height={height} width={width} />;
```

#### メリットとデメリット
- メリット
    - コンポーネントごとに独立したスタイルを定義することができる
- デメリット
    - コンポーネントがレンダリングされるたびにJS内部のCSSがロードされるため、性能低下に繋がりやすい

---

### :memo: CSSフレームワーク
Bootstrapや, TailWind CSSを用いる。
こちらは割愛します。

---

### まとめ
CSS-In-JSのパフォーマンス影響がどれくらいあるのかも気になるところですが、個人的にはCSS Moduleを採用していこうと思いました。
Raspberry Pi 5からL6470モータードライバ経由でステッピングモーターを駆動させる

[パソコン並の性能を持つ](https://xtech.nikkei.com/atcl/nxt/column/18/02756/022600001/)と言われるRaspberry Pi 5ですが、RP1と呼ばれるI/Oコントローラーが追加されました。これに伴い[GPIOの番号に互換性がなかった](https://xtech.nikkei.com/atcl/nxt/column/18/01109/040700054/)りして、良く使われてきたドライバーが動かなかったりします。ここでは、秋月電子の[L6470使用 ステッピングモータードライブキット](https://akizukidenshi.com/catalog/g/g107024/)を使ってモーターを動かしながらSPI通信の方法をみていきます。

## 必要なもの

* Raspberry Pi 5
* [L6470 ステッピングモーター・ドライバー](https://akizukidenshi.com/catalog/g/g107024/)
* [バイポーラ・ステッピングモータ](https://jp.misumi-ec.com/vona2/detail/221005433134/?HissuCode=SS2421-5041)
* [12V ACアダプター](https://amzn.to/3QObFSW)
* [DCジャック](https://akizukidenshi.com/catalog/g/g105148/)

## 準備

下図のようにステッピングモーター等を接続します。

![](https://raw.githubusercontent.com/horie-t/omni-mouse/main/docs/images/L6470StepperMotor.png)

## 実行

Pythonで制御するために、[公式サイトで紹介](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#using-spidev-from-python)されている[spidev](https://pypi.org/project/spidev/)を使用します。インストールされていない場合は以下のコマンドを実行してインストールします。

```bash
pip install spidev
```

次に、以下のプログラムを作成し実行します。

```python:L6470_motor_drive.py
import spidev
import time

# SPIの初期化
spi = spidev.SpiDev()
spi.open(0, 0)
spi.bits_per_word = 8
spi.cshigh = False
spi.loop = True
spi.no_cs = False
spi.lsbfirst = False
spi.max_speed_hz = 4000000
spi.mode = 3
spi.threewire = False

# しばらく何もしない(NOP)
spi.xfer([0x00])
spi.xfer([0x00])
spi.xfer([0x00])
spi.xfer([0x00])

# HOMEポジションへ
spi.xfer([0x70])

# 最大回転速度設定
spi.xfer([0x07])
spi.xfer([0x20])

# モータ停止中の電圧
spi.xfer([0x09])
spi.xfer([0xFF])

# モータ定速回転中の電圧
spi.xfer([0x0A])
spi.xfer([0xFF])

# モータ加速中の電圧
spi.xfer([0x0B])
spi.xfer([0xFF])

# モータ減速中の電圧
spi.xfer([0x0C])
spi.xfer([0xFF])

# ステップモード
spi.xfer([0x16])
spi.xfer([0x00])

time.sleep(3)

while True:
    # 目標速度で正転させる
    spi.xfer([0x50])
    # NOP
    spi.xfer([0x00])
    # 回転速度を設定
    spi.xfer([0x20])
    # NOP
    spi.xfer([0x00])

    # 1秒回転
    time.sleep(1)

    # 停止
    spi.xfer([0xB8])
    # 1秒停止
    time.sleep(1)
```
FlutterでProxyman等を使うときのHTTPクライアントコード

## はじめに
ProxymanやCharlesを使うときhttpパッケージやdioパッケージの利用箇所に変更が必要です。
Proxymanの手順にもやり方が書いてあるのですが、書き方がだいぶ古いので最近対応したときのコードを残したメモです。

https://docs.proxyman.io/debug-devices/flutter

## dioパッケージの場合

```dart
  final dio = Dio();

  // デバッグ中だけ設定
  if (kDebugMode) {
    dio.httpClientAdapter = IOHttpClientAdapter(
      createHttpClient: () {
        final client = HttpClient();
        client.findProxy = (uri) {
          // dart-defineやdart-define-from-fileから読み取る場合
          const yourLocalIp = String.fromEnvironment('YOUR_LOCAL_IP');
          const proxyPort = String.fromEnvironment('PROXY_PORT');
          final proxy = Platform.isAndroid
              ? '$yourLocalIp:$proxyPort'
              : 'localhost:$proxyPort';

          return 'PROXY $proxy';
        };
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) => Platform.isAndroid;
        return client;
      },
    );
  }
```

dio_proxy_adapterってパッケージもありますが、全然メンテされてないのでオススメできません。

https://pub.dev/packages/dio_proxy_adapter

## httpパッケージの場合

```dart
  final httpClient = HttpClient();

  // デバッグ中だけ設定
  if (kDebugMode) {
    httpClient.findProxy = (uri) {
      // dart-defineやdart-define-from-fileから読み取る場合
      const yourLocalIp = String.fromEnvironment('YOUR_LOCAL_IP');
      const proxyPort = String.fromEnvironment('PROXY_PORT');
      final proxy = Platform.isAndroid
          ? '$yourLocalIp:$proxyPort'
          : 'localhost:$proxyPort';

      return 'PROXY $proxy';
    };
    httpClient.badCertificateCallback =
        (X509Certificate cert, String host, int port) => Platform.isAndroid;
  }

  final client = IOClient(httpClient);
```

## おまけ(dart-define-from-fileの部分)

こんな感じのjsonを用意します。
```dev.json
{
    "YOUR_LOCAL_IP": "192.168.0.30",
    "PROXY_PORT": "9090"
}
```

起動時にこうします。
```
flutter run --dart-define-from-file=dev.json
```

VSCodeならこんな感じです。
```launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "debug",
            "request": "launch",
            "type": "dart",
            "args": [
                "--dart-define-from-file=dev.json"
              ]
        },
```
Google Chrome用Qiitaのリンクを取得するブックマークレット

# 手順
<ol> 
<li>Google Chormeを開く
<li>適当にブックマークをする
<li>タイトルをQURLとかユニークにする
<li>Urlのところに以下のスクリプトをコピペする
<li>コピペすると改行コードが消えて１行になる
</ol>

# Javascript

```javascript
javascript:(function(){
  var title = "[" + document.title + "]"; 
  var url = "(" + window.location.href + ")";
  var text = title + url;
  navigator.clipboard.writeText(text);
})();
```

## ポイント
### `)`の意味がわからない
`})();`
ラストの２番目の`)`は対応するものがない。だからと言って削除すると全く動かない。

### alertはない
なので、何の予告もなくクリップボードに入る

## ソース
かってにAIが作っても危ないので
[Document - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Document)
>Document.title
現在の文書のタイトルを設定または取得します。


[Window - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Window)
> Window.location
window オブジェクトのロケーション、または現在の URL を取得 / 設定します。

[誰も教えてくれないJavaScriptで登場するDOMを心底理解する【window,document,event,addEventListener,NodeList,Array,イベント】](https://lorem-co-ltd.com/dom-event-basic/)

[JavaScriptのwindowオブジェクトとdocumentオブジェクトについて(DOM操作、イベントリスナーなど) #JavaScript - Qiita](https://qiita.com/Hashimoto-Noriaki/items/fa6da7b72069b9935ccc)
# あまりうまくいかない
今回はGeminiのアシストで作ったが、しょせんAIの作るコードはテストしないと動かない
へんなものを作ってくる。

## `var url = encodeURIComponent(window.location.href);`

```html
https%3A%2F%2Fwww.google.co.jp%2
```
このようにやらなくていいところまでエンコードする
エンコードするとリンクすらしない

## `document.lastmodified`
定義されていないことがほとんどなので、undifinedが返ってくる
できれば記事の日付があれば取得したいが、世の中そんなに甘くない
Godot 4.xのLabelの文字を太くする方法

# 経緯
文字を太くしたくて試行錯誤した結果発見したためこの世に訴えます。
# 環境
Godot v4.2.2
# 方法
1. まずラベルを追加します。既にあれば要りません。
1. インスペクタ(ノードのプロパティ)を開きます。
1. Control部の中のTheme Overrides→Colorsの中のFont ColorとFont Outline Colorをお好みの文字の色にします。
1. Theme Overrides→Constants→Outline Sizeをお好みの大きさにします。
これで文字を太くできます。

どうやら、Outline等の設定は文字の太さ関係の設定のようです。

> よいGodotライフを！
リストの縦結合：SQL文のGroup By Order ByをJavaでやる方法

## 開発環境
- Java：8
- IDE：Intellij
- build:gradle

## java機能

先ずリストを格納するクラスを用意する
```java
public class Member {
    public int groupID;
    public int memberID;
    public int seatID;
    public String name;

    public Member(int groupID, int memberID, int seatID, String name) {
        this.groupID = groupID;
        this.memberID = memberID;
        this.seatID = seatID;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Member{" +
                "groupID=" + groupID +
                ", memberID=" + memberID +
                ", seatID=" + seatID +
                ", name='" + name + '\'' +
                '}';
    }
}
```

次にリストを操作機能を提供するクラスを作成
```java
public class MemberListProcessor {
     
    // ①
    public List<Member> combineAndSortLists(List<Member> list1, List<Member> list2) {

        // ②
        List<Member> combinedList = new ArrayList<>(list1);
        combinedList.addAll(list2);

        // ③
        Map<Integer, List<Member>> groupedMap = combinedList.stream()
                .collect(Collectors.groupingBy(member -> member.groupID));

        // ④
        return groupedMap.values().stream()
                .flatMap(group -> group.stream()
                        .sorted(Comparator.comparingInt((Member m) -> m.memberID)
                                .thenComparingInt(m -> m.seatID)))
                .collect(Collectors.toList());
    }
}
```
説明
- ①：二つのリストを結合して返すメソッド
- ②：二つのリストを結合する
- ③：結合したリストを`groupID`グルーピングする
- ④：グルーピング後のリストを`memberID`、`seatID`でソート後返却する


テストしてみる
```java
public class Main {
    public static void main(String[] args) {

        setMember();
    }

    public static void setMember() {
        List<Member> list1 = new ArrayList<>();
        list1.add(new Member(1, 1, 1, "A"));
        list1.add(new Member(2, 6, 5, "B"));
        list1.add(new Member(2, 4, 2, "C"));

        List<Member> list2 = new ArrayList<>();
        list2.add(new Member(2, 3, 5, "D"));
        list2.add(new Member(2, 5, 3, "E"));
        list2.add(new Member(1, 2, 4, "F"));

        MemberListProcessor pro = new MemberListProcessor();

        List<Member> combinedList = pro.combineAndSortLists(list1, list2);
        combinedList.forEach(System.out::println);
    }
}
```

出力結果：想定通り
```
Member{groupID=1, memberID=1, seatID=1, name='A'}
Member{groupID=1, memberID=2, seatID=4, name='F'}
Member{groupID=2, memberID=3, seatID=5, name='D'}
Member{groupID=2, memberID=4, seatID=2, name='C'}
Member{groupID=2, memberID=5, seatID=3, name='E'}
Member{groupID=2, memberID=6, seatID=5, name='B'}
```
ES Modulesからexportされている関数や変数の一覧を取得する方法

## はじめに

ESModuleを動的にロードして、そのモジュールでexportされた関数や変数の一覧を取得する方法です

`dynamic import`でロードすると、moduleの`key`がexportした名前になっていました

https://github.com/murasuke/list_module_export

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/import

## 調査対象モジュール

関数、変数、classをexportするだけのモジュールです

```javascript:exports.mjs
// 関数、変数、classをexport(確認用)

export function func1(args) {
  console.log(`called func1(${args})`);
}

export const func2 = (args) => {
  console.log(`called func2(${args})`);
};

export const CONST_VAL = 'const text';

export class export_class {}

let default_value = 123;

export default default_value;
```


## moduleを動的に読み込み、exportされた変数や関数の一覧を表示する

* `dynamic import`を利用して動的にロードする
* moduleのkeyがexportされた変数名や関数名(default exportは`default`という名前になっている)

* classはコンストラクタ関数としてexportされますが、通常の関数と判断する方法がありませんでした(new をつけずに呼び出せば実行時エラーになるので判断できなくはないですが・・・)

```javascript:main.mjs
// 動的に読み込んだmoduleから、exportされた変数や関数を抜き出すサンプル
const module = await import('./exports.mjs');

function isConstructor(func) {
  // コンストラクタ関数か、通常の関数か？を判断する方法がないので'class'という文字があるかでチェックしている
  return /\bclass\s/.test(func.toString());
}

// exportされた名前がmoduleのキーになっている
console.log(Object.keys(module));

// キーを使いexportされた各種値を取り出して型を確認する
for (const key of Object.keys(module)) {
  const obj = module[key];
  console.log(`${key}:`);

  if (typeof obj == 'function') {
    if (isConstructor(obj)) {
      console.log(`  constructor`);
    } else {
      console.log(`  function`);
      obj(key); // 関数を呼び出す
    }
  } else {
    // 値の表示
    console.log(`  variable(${typeof obj}) ${obj}`);
  }
}

```

## 実行結果

node環境でもブラウザでも同じ結果になります

```
$ node main.mjs
[ 'CONST_VAL', 'default', 'export_class', 'func1', 'func2' ]
CONST_VAL:
  variable(string) const text
default:
  variable(number) 123
export_class:
  constructor
func1:
  function
called func1(func1)
func2:
  function
called func2(func2)
```
Ubuntu Server 24.04 LTSをKVMで動かしてみた

# はじめに
Ubuntu Server 20.04.6 LTSのKVMで、Ubuntu Server 24.04 LTSを動かしたときのメモです。

# 参考にしたサイト
- https://qiita.com/fukunagt/items/5c6932db5bef703273ea
  - Ubuntu Server 22.04.3 LTSの手順を、本記事のUbuntu Server 24.04 LTSでも試してみました。結果から言うと、同手順で動きました。

# 環境
## ホストOS
- Ubuntu Server 20.04.6 LTS

## ゲストOS
- Ubuntu Server 24.04 LTS

# ディレクトリ構成
```
/home/user
 |
 +-- dvd
 |    |
 |    +-- ubuntu-24.04-live-server-amd64.iso
 |
 +-- kvm
      |
      +-- ubuntu24-51
           |
           +-- install.sh
           |
           +-- ubuntu24-51.qcow2
```
- 上記ディレクトリ構成はサンプルです。適宜変更してください。
- 筆者のディレクトリの命名規則として、ubuntu24-51の末尾の`51`は、IPアドレスの最終オクテットを表しています。左記の場合、この仮想マシンには、192.168.122.51を割り当てています。

# 手順
1. 以下からUbuntuのインストーラーをダウンロードしてください。
   - https://ubuntu.com/download
1. 仮想ディスクを作成してください。
   ```sh
   qemu-img create -f qcow2 ubuntu24-51.qcow2 128G
   ```
1. install.shファイルを作成してください。
   ```sh
   touch install.sh
   ```
   ```sh
   chmod +x install.sh
   ```
1. vimなどでinstall.shを開き、以下のように編集してください。
   ```sh
   virt-install \
   --name ubuntu24-51 \
   --hvm \
   --virt-type kvm \
   --ram 8192 \
   --vcpus 4 \
   --arch x86_64 \
   --os-type linux \
   --disk /home/user/kvm/ubuntu24-51/ubuntu24-51.qcow2 \
   --network bridge=virbr0 \
   --graphics none \
   --serial pty \
   --console pty \
   --location /home/user/linux/dvd/ubuntu-24.04-live-server-amd64.iso,kernel=casper/vmlinuz,initrd=ca   sper/initrd \
   --extra-args "console=ttyS0"
   ```
   - GUIを入れていない環境なので、```--graphics none```を指定しています。
1. install.shを実行すると、インストーラーが起動します。
   ```sh
   ./install.sh
   ```

# さいごに
Ubuntu Server 24.04もUbuntu Server 22.04と同じ手順でインストールできました。
margin-inlineが便利だった


# margin-inlineについて
margin-inline は「論理プロパティ」で、要素のインライン方向(横方向)のマージンを設定するためのもの。
文字の記述される方向（書字方向）によって方向が変わる。

margin-inlineは、margin-inline-startとmargin-inline-endのショートハンドで
```
margin-inline: auto;
```
は、
```
margin-inline-start: auto;
margin-inline-end: auto;
```
と書くことも可能。
ブランチを削除してやり直したい時のコマンド手順

# はじめに
よく使うブランチ関係のコマンドをアウトプットしています
初心者なので、誤りありましたら教えていただけると嬉しいです😃
統合ブランチをdevelop、作業ブランチをfeatureとしています

# ローカルブランチの削除方法
リモートにプッシュしていない場合、ローカルブランチを削除するだけでやり直すことができます

### 手順
現在作業ブランチにいる場合、作業ブランチを削除することができません
そのため、一旦削除対象以外のブランチに切り替えます
(mainでもdevelopでもいいです)

・ブランチの切り替え
```
$ git checkout develop
```

・作業ブランチを削除
```
$ git branch -D ブランチ名
```

作業ブランチでコミットをしていなかった場合に、
ブランチを削除したにも関わらず作業した内容が残っている場合があります
そういう時には、削除対象以外のブランチに切り替えた時にターミナルに以下が出力されているかと思います

```
ec2-user:~/environment/アプリ名 (feature/作業名) $ git checkout develop
M app/controllers/admin/confirmations_controller.rb
M app/controllers/admin/customers_controller.rb
M app/controllers/admin/genres_controller.rb
︙
Switched to branch 'develop'
```
この表示は作業ブランチで修正された箇所を引き継いでdevelopブランチで作業を続けられることを意味しています
しかし、作業をやり直したいわけですから余計なお世話ですよね

なので、まっさらな状態で新しく作業を始めたい場合は、以下のコマンドを入力します
```
$ git reset --hard HEAD
```
これで直前のコミット時点の状態に戻り、変更が全て破棄されます

:::note alert
注意
上記のコマンドで修正状態を元に戻ししても、
新しく作成したviewファイルなどのは削除されず、コードの中身もそのままです
ステータスを確認しておきましょう！
```
$ git status
```
:::
以上のコマンドでやり直すことができます！

:::note warn
最新の統合リポジトリを取得する癖をつけましょう
コンフリクトが起きる可能性があります！

・リモートの（統合ブランチの）最新版をローカルに反映させる
```
$ git pull origin develop
```
:::
[ブランチの切り方はこちら](https://qiita.com/3rarara/items/1579ff5e93e96e39c79e "ブランチ関係のコマンド まとめ")

# リモートブランチの削除方法
・リモートブランチを削除
```
$ git push origin --delete ブランチ名
```

すでにそのリモートブランチが削除されている場合、以下のエラーが発生する可能性があります
```
error: unable to push to unqualified destination: remoteBranchName The destination refspec neither matches an existing ref on the remote nor begins with refs/, and we are unable to guess a prefix based on the source ref. error: failed to push some refs to 'git@repository_name'
```
m1 macでnodebrew installできないverがある時


# 事象
m1 macでnodebrewを使用して指定のnodeのバージョンをインストールするときに、対応していないverがある場合がある。

```
nodebrew install v10.15.2
v10.15.2 is not found
```

# 原因
m1 mac（arm64）に対応していないnodeのバージョンのため。

# 解決方法
arch -x86_64を頭につけるとインストールすることが可能
```
arch -x86_64 nodebrew install [version]
```
- archコマンドでアーキテクチャ(実行環境の設定)をx86_64に指定する
M5Stack CoreMP135のI2C/SPI内部配線まとめ (上級開発者向け)

今までに判明したCoreMP135のまとめ。
ドライバはM5Stack公式のbuildroot externalにあるものの説明。

これ以外はDTSを読めば大抵わかる。

誰の役に立つのかはすごくわからないが一応書いておく。

## 1. SPI系
### 1.1. SPI0
#### 1.1.1 ILI9342C
ILI9342Cはディスプレイ制御IC。

CSは`&gpioh 5 GPIO_ACTIVE_HIGH`。

https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/ILI9342C-ILITEK.pdf

ドライバは`fb_ili9341`の改造版。

https://github.com/m5stack/CoreMP135_buildroot-external-st/blob/st/2023.02.10/board/m5stack/coremp135/patches/linux/0005-fbdev-fb_ili9341_m5.patch

ついでにだが私の変更を加えたドライバもおいておく。

https://github.com/MeemeeLab/linux/blob/m5stack-coremp135/drivers/staging/fbtft/fb_ili9342c.c

## 2. I2C系
### 2.1. I2C1
背面内部ピンソケット。

### 2.2. I2C2
こちらも背面内部ピンソケット。

### 2.3. I2C3
```
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- 34 -- -- -- UU 39 -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
```

#### 2.3.1 AXP2101 `0x34`
電源制御IC。
アドレスは`0x34`。

https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/products/core/Core2%20v1.1/axp2101.pdf

このICで電源を落とすなどの動作ができる模様。
注意として**このICのDLDO1にバックライトがつながっている。**
バックライトがついていないとディスプレイが動作していてもわからない。

ドライバは`fb_ili9341`の改造版にくっつけてあるが、これはバスなどハードコードかつインデントが揃っていないなど見にくい。
もちろんDTSなど使わない戦法らしい。

https://github.com/m5stack/CoreMP135_buildroot-external-st/blob/st/2023.02.10/board/m5stack/coremp135/patches/linux/0005-fbdev-fb_ili9341_m5.patch

自分がバックライト用に作ったドライバも乗せておく。

https://github.com/MeemeeLab/linux/blob/m5stack-coremp135/drivers/video/backlight/axp2101_m5stack_bl.c

自分の作った方はDTSに
```
&i2c3 {
    ...
	backlight@34 {
		compatible = "m5stack,axp2101";
		reg = <0x34>;
		status = "okay";
	};
};
```
のようにして使う。

#### 2.3.2 FT6236 `0x38`
タッチスクリーン。
アドレスは`0x38`。

https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/Ft6336GU_Firmware%20%E5%A4%96%E9%83%A8%E5%AF%84%E5%AD%98%E5%99%A8_20151112-%20EN.xlsx

ドライバはもうすでにupstreamされている。

特に言うことなし。

#### 2.3.3 LT8618SXB `0x39`
HDMIトランスミッタ。
アドレスは`0x39`。

https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/products/core/M5CoreMP135/LT8616SX.pdf

一番の目玉。

ドライバはない。ユーザースペース側でやり取りしている。

しかも、このユーザースペース側のプログラム、バイナリBLOBしかない。
すごく悲しい。

https://github.com/m5stack/CoreMP135_buildroot-external-st/blob/st/2023.02.10/board/m5stack/overlay/usr/local/m5stack/lt8618sxb_mcu_config

プロプライエタリな理由は多分ベンダー側から公開しないように念を押されている気がする。
データシートもどれだけ探してもブリーフしかない。
I2Cのレジスタについて語っているPDFは他の型番含め一つも見当たらない。

HDMIのライセンス的なのもある気がしている。

自分は[プロプライエタリなソフトウェアはしばしばマルウェアである - GNU](https://www.gnu.org/proprietary/proprietary.ja.html)
みたいなタイプの思想が偏った人間なのでどうしようか悩んでいる。

ただこいつがないとHDMIは一生動かない。どうしたものか。

一つ方法を思いついているが実際にできるとわかるまで記載しないことにする。

追記。M5Stackにメンションしてみた。
レジスタは公開できるかもとのこと。
一週間近くかかるらしいので気長に待つか。

#### 2.3.4 BM8563 `0x51`
RTC。
アドレスは`0x51`。

https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/BM8563_V1.1_cn.pdf

ドライバはなぜか`nxp,pcf8563`。upstream済み。動作している。
どうもPCF8563の互換ICのよう。
動いているのであまり気にしてはいない。
複数のインスタグラムアカウントのインサイトデータをGoogle Apps Script (GAS) とLooker Studioで可視化して学んだ5つのこと

クライアントからの依頼で、複数（10個ほど）のインスタグラムアカウントのインサイトデータを可視化するダッシュボードを作成することになりました。手作業では煩雑で時間がかかるため、Google Apps Script (以下GAS)を使ってデータを自動的に取得し、Looker Studio（旧Google Data Studio）でダッシュボードを構築しました。この記事では、その過程で学んだ5つの重要なポイントをご紹介します。


## 学び1　最大実行時間に気をつける
GASには最大実行時間が6分という制限があるため、長時間かかる処理はタイムアウトしてしまう可能性があります。インスタグラムのインサイトデータを複数アカウント分取得する場合、各アカウントごとにデータを取得し、一度に全ての処理を行わないように注意が必要です。
今回はGASの中で、1つのアカウントのインサイトデータの取得が終わったら、一定時間後に次の処理が行われるようにトリガーを設定するようにしました。
```
// インサイトデータ取得の処理の後にトリガーを設定する
const trigger = ScriptApp.newTrigger(${実行したい関数}).timeBased().at(${1分後}).create();
```

参考: [Google Apps Scriptの割り当てと制限](https://developers.google.com/apps-script/guides/services/quotas?hl=ja)


## 学び2　インサイトデータの取得と画像の保存処理を分ける
今回、インスタグラムの投稿の画像も可視化のする必要がありました。画像のデータを一度に取得しようとすると処理が重くなりがちです。また前述の最大実行時間の制限にもあたりやすくなります。そのため、インサイトデータの取得と画像の保存処理を別々に行うことをおすすめします。まずインサイトデータのみ取得し、それを保存した後に画像データを取得するスクリプトを実行すると、効率的に処理が進められます。


## 学び3　データの保存先としてBigQueryを使う
インスタグラムのインサイトデータは大量になることがあります。そのためスプレッドシートでの管理が難しい場合があります。  
今回は、クライアントが管理したいインスタグラムが10個ほどあり、日々の投稿数もかなり多いような状況だったため、Google Cloud Platform (GCP)のBigQueryをデータの保存先として利用しました。BigQueryは大量のデータを扱うことを得意としているデータベースであり、Looker Studioとの相性も良いためおすすめです。


## 学び4　スクリプトはGCPプロジェクトに紐づける
GASのシステムを安定的に運用する上では、GCPプロジェクトに紐づけることが重要です。  
これにより、複数のGASを管理している場合、ログが一元管理できるようになったり、GASでエラーが起きたときにSlack等へアラートを飛ばせるようになったりします。
紐づけ方法は以下のとおりです。

1. GCP プロジェクトを新しく作って、プロジェクトの設定を切り替える必要があります。以下のメニューから「プロジェクトの設定」に移動
![スクリーンショット 2024-05-17 22.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794884/bac74949-d7f5-a877-65ca-1a368e9e32e0.png)

2. Cloud Logging の機能を有効化した Google Cloud Platform (GCP) プロジェクトのプロジェクト番号を紐づける
![スクリーンショット 2024-05-17 22.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794884/160b12c6-b2d3-52e8-f724-ddc4ce3eabba.png)

参考: [Google Apps ScriptでCloud Loggingを使用する](https://developers.google.com/apps-script/guides/logging?hl=ja#using_cloud_logging)


## 学び5　ダッシュボードにはLooker Studioがおすすめ
最後に、インサイトデータを可視化するためのツールとしてLooker Studioを強くおすすめします。
Looker Studioは、スプレッドシートやBigQueryに保存したデータを簡単にインポートしてダッシュボードを作成できます。また、豊富なビジュアライゼーションオプションやカスタマイズ機能を活用することで、クライアントのニーズに応じた見やすいダッシュボードを作成することが可能です。

https://lookerstudio.google.com/embed/reporting/345131f0-973d-478c-9292-e40f9f02e56a/page/p_jex2nb6y9c

## 最後に
これらの学びを参考にしていただくことで、インスタグラムのインサイトデータを効率的に取得し、効果的に可視化することができると思います。これから同様のプロジェクトに取り組む方々の参考になれば幸いです。

## 宣伝
GASラボでは、便利な自動化ツール（GAS製・100種類以上）、新規サービス、テンプレートを開発・公開しております。
最新情報については、Twitter(X）でも配信しておりますので、是非チェックしていただけると幸いです。

[【GASラボ】Twitter（X）アカウント](https://x.com/gas93740656?ref_src=twsrc%5Etfw%7Ctwcamp%5Eembeddedtimeline%7Ctwterm%5Escreen-name%3Agas93740656%7Ctwcon%5Es1_c1)
ITパスポート 財務諸表

・財務諸表
企業の財政状態や経営成績をステークホルダ（株主や債権者などの利害関係者）へ報告するために作成される計算書類

・ディスクロージャ
企業の財務状態や経営成績を外部に公開すること

・貸借対照表
決算日における企業の資産、負債、純資産を記載したもの
資産＝負債＋純資産

・買掛金
後で支払う代金
・売掛金
後で支払われる代金

・流動比率
流動負債に対する流動資産の割合を示した指標
流動比率（％）＝流動資産÷流動負債x100

・固定比率
自己資本に対する固定資産の割合を表した指標
固定比率（％）＝固定資産÷自己資本x100

・自己資本比率
総資産に対する自己資本の割合を示した指標
自己資本比率（％）＝自己資本÷総資産x100

・損益計算書
会計期間に発生した収益と費用によって、企業の営業成績を表示したもの

・営業利益（本業の儲け）
営業利益＝売上総利益ー販売費及び一般管理費

・経常利益（本業以外も含めた通常業務での儲け）
経常利益＝営業利益＋営業外収益ー営業外費用

・ROE
自己資本に対する当期純利益の割合を示した指標
ROE（％）＝当期純利益÷自己資本x100

・ROA
総資産に対する当期純利益の割合を示した指標
ROA（％）＝当期純利益÷総資産x100

・売上総利益率（粗利率）
売上高に対する売上総利益の割合を示した指標
売上総利益率（％）＝売上総利益÷売上高x100

・総資産回転率
総資産に対する売上高を示した指標
総資産回転率（回）＝売上高÷総資産

・在庫回転率
平均在庫高に対する売上高を示した指標
在庫回転率（回）＝売上高÷平均在庫高

・キャッシュフロー計算書
会計期間におけるキャッシュフロー（現金の流れ）の状況を営業活動、投資活動、財務活動の三つの活動区分に分けて表したもの

・売上総利益＝売上高ー売上原価
・税引前当期純利益＝経常利益＋特別利益ー特別損失
・当期純利益＝税引前当期純利益ー法人税、住民税、事業税
robloxでassistant その56

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
ミサイルを作れ。

# 方針
RunServiceサービスを使う。

# 手順
- WorkSpaceに、partを追加
- partに、scriptを追加
- スクリプトを書く。
```
print("ok3")

local workspace = game.Workspace
local part = script.Parent
local function explode()
	local explosionSound = Instance.new("Sound")
	explosionSound.SoundId = "rbxassetid://5137964328"
	explosionSound.Parent = game.Workspace
	local explosion = Instance.new("Explosion")
	explosion.BlastRadius = 10
	explosion.BlastPressure = 500000
	--explosion.Position = part.Position
	explosion.Parent = game.Workspace
	explosionSound:Play()
end
part.Touched:Connect(function(hit)
	if hit.Name == "Baseplate" then
		print("okok")
		explode()
		part:Destroy()
	end
end)
```
- ReplicatedFirstに、localscript追加。
- スクリプトを書く。
```
print("ok1")

local function getRadian(x, y, x2, y2) 
	local radian = math.atan2(y2 - y, x2 - x)
	return radian
end	

local function rad2deg(rad) 
	local degree = rad * 180 / math.pi
	return degree
end		

local function getDistance(x, y, x2, y2) 
	local distance = math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y))
	return distance
end
	
local workspace = game.Workspace
local players = game:GetService("Players")
local player = players.LocalPlayer
local part = workspace:WaitForChild("Part")
part.Size = Vector3.new(1, 1, 1)
part.Anchored = false
part.Position = Vector3.new(400, 400, 0)
local x = 10
local y = 10
local run = game:GetService("RunService")
local speed = 1.4
wait(2)
run.RenderStepped:Connect(function()
	local rad = getRadian(player.Character.HumanoidRootPart.Position.X, player.Character.HumanoidRootPart.Position.Y, part.Position.X, part.Position.Y)
	local dis = getDistance(player.Character.HumanoidRootPart.Position.X, player.Character.HumanoidRootPart.Position.Y, part.Position.X, part.Position.Y)
	local deg = rad2deg(rad)
	local angle = deg
	--print(dis)
	local dx = speed * math.cos((math.pi / 180) * angle)
	local dy = speed * math.sin((math.pi / 180) * angle)
	x -= dx
	y -= dy
	part.Position = Vector3.new(x, y, -1)
end)




```

以上。
Twitter APIでフォロー対象抽出アプリを作ったら精度が良すぎてアカウントロックされた話

昨日URLのドメインが完全にx.comになったX(旧Twitter)について、APIの有料化＆厳しい制限になってしまっているので時効ということでフォロー対象を抽出するアプリを作った時のことを書こうと思います。

※まだまだ「Twitter」という名称が頭から抜けない人が多いと思いますので、この記事ではXのことをTwitterと書いています。

## フォロー対象をリストアップするアプリを作った

TwitterのAPIがまだ無料で使えた頃、フォロワーを増やすためにフォロー対象をリストアップするアプリを作りました。

やってることは単純で、ツイートについているいいねや特定のアカウントのフォロワーをうまいこと抜き出してきて画面に表示するというシンプルなアプリです。

自分からフォローするというのはTwitterに限らずSNS全般で有効なやり方で、自分のアカウントと相性がいいアカウントというのもあります。

またフォローとフォロワーの比率やフォロワー数などの特徴から「フォローが高確率で返ってくるアカウント」というのも存在します。

それらを踏まえてアプリを作りました。

### 作った機能

1. 指定したアカウントの直近3日のツイートにいいねしている人を定期実行で取得
2. 指定したアカウントのフォロワーを定期実行で取得
3. 1と2で抽出したアカウント一覧をジャンルごとにカテゴリ分けして表示
4. 3で取得したアカウント一覧を、フォロー数やフォロワー数などでフィルターして表示
5. 4で表示したユーザー一覧に関して、ユーザーのページを別タブで開く機能（ここからフォローボタンを押す）
6. 4で取得した結果の中から、指定したアカウントを除外する機能（過去にフォローした人を再度フォローしないようにするため）
7. 指定したアカウントを6の除外リストに追加する機能

1と2は後述しますがGASを使って定期実行で動かしました。

上記機能を使うと特定のジャンルでフォローが返ってくるであろうアカウントの一覧が作れます。

アカウントのリストを作ることはできますが、フォローをAPI経由で行うとイマイチ反応が悪かったのでプロフィールにアクセスしてフォローボタンからフォローする形にしました。

フィルターを改良していくと精度がよくなっていきフォローのスピードが上がっていきましたが、アプリを使って動かしていたアカウントのうち1つがロックされてしまいました。

## なぜアカウントロックがかかってしまったのか？

アカウントロックがかかってしまった原因は単純で、**フォローするスピードが早すぎたから**です。

Twitterをブラウザで開いたり公式のクライアントアプリでフォロワー一覧などのユーザーをフォローしていく場合、一覧にいるすべてのアカウントがフォローが返ってきやすいアカウントではありませんし、フォロワーが多すぎるなどフォローが返ってきにくいアカウントも存在します。

そのようにノイズがある中で1人ずつページを見ていけばフォローの間隔は平均して数秒〜10秒ぐらいは空きます。

一方で

- 過去にフォローしたことがある人は表示しない
- フォロワー数がフォローに比べて多すぎるアカウントは表示しない

などの条件で絞り込んだフォロワー一覧は精度がどんどん高くなっていき、アカウントのプロフィールのページを開いたら何も考えずにフォローすることがほとんどになります。

その結果として**フォローが返ってきやすい人を1.5秒ぐらいに1人フォローできる**精度のものが出来上がり、調子に乗ってその速さでフォローしていったらアカウントロックに引っかかりました。

それぐらいのスピードでフォローしてもロックされないことも多いですが、**上記のような高速フォローを繰り返し行う→うっかりアカウントロックの閾値を超えてしまった**と個人的に捉えています。

今後同じようなことをやる機会が出てきたら数秒待った方が安全です（といってもロックされる時はロックされますが。。）。

## 使った技術など

- TwitterのAPIを叩くアプリ: PHP
- 定期実行: GAS(上記PHP製アプリのエンドポイントを叩く用)
- ツイート取得対象やフォロワー取得対象のアカウントの管理: GAS上に配置したスクリプトを編集して管理
- 除外リストの読み書き: PHP, MySQL
- UI: Vue.js(上記レンタルサーバーのスクリプトを叩いて、フォロー対象リストや除外リストを読み込む)
- 開発環境: M1 Mac, Docker, Node.js

ツイート取得やフォロワー取得の対象はUI作ってDBに読み書きする方が良いですが、当時は面倒でスクリプトにベタ書きしていました。

PHPやVue.jsはちょっとしたツールを作るのにすごく便利で、ログイン機能も簡単に付けられて良い言語だと思います。

上記したフォロワー抽出は実際に手作業で動かした知見をもとに作ったものであって、正直自動化なしでもやろうと思えばそれなりにやれます。

最初から自動化でなんでも解決するのは良くないですが、手を動かしたときの知見をもとにして自動化を行うというのはすごくありです。

むしろ手作業でやった経験がないとPHPやjavascriptのような便利な技術があったからといって全然活かせません。

## まとめ

今はTwitterのAPIが有料かつBasicプランは制限がかなりきついものになってしまいました。

そのためアカウントの立ち上げ期として自分からフォローしてフォロワーを増やすならそれなりに戦略が必要です。

またプログラミングに関する記事や動画でよくある「XXを自動化してみた」的なものも、手作業で結果が出ることがわかってからやった方が良いと思います。

自動化そのものは掛け算に過ぎなくて、手作業で作った1や2を自動化で10や100にするようなものだと思っています。

さらにいうと「どういう目的のためにTwitterをやるの？」とかも考えるべきで、「とりあえず人を集めてから考える」という考え方もあまり良くないなぁと思います。
promiseを即時関数を使わずに書いてみた

promiseがやっとわかった（気がした）ので投稿します。そもそもPythonからはいった身としては、promiseのサンプルに出てくる即時関数が多くて理解しにくいと感じます（単に慣れていないだけですが）。そこで即時関数を使わずに理解しようと試みたという感じです。

# 大前提
そもそもpromiseとはなんのためにあるか、一度整理してみると

①2つの関数ex1とex2があって、非同期処理が含まれているときはどっちが先に終わるかわからない
②画像の読み込みだとそれでも問題がない（どっちが先に表示されてもok）
③しかし、データベースの読込のように、入力をまって処理をするように場合は困る。データがないのに処理を始めてしまうので
④そこでpromiseの登場。ex1の終了をまってex2を開始する

# イメージで捉える
まだピンとこない場合は、リレー競争を思い受かべてみてください。
第１走者、第２走者がいます。よーいどんで第１走者が走りだしますが、非同期のままだと第２走者も走り出しちゃいます。第２走者が走り出さないようにするのがpromiseで、バトンに相当するのがresやrejという関数です。バトンを受け取ってから第２走者が走り出します。promiseの場合はバトンの中にメッセージがあって、やり取りができるというイメージです。




# stepごとに書いていきます
まず最初にPromiseのインスタンスをつくるところからになります。Promiseの正体はインスタンスで、引数にはexecutor関数（最初に実行させたい処理）を取ります。

```
const P1=new Promise(ex1)			//Promiseの正体はインスタンスである。引数には関数（実行させたい処理）を取る。名前をex1とした
P1.then(ex2)						//.then()も関数を引数に取る、引数は成功時に実行させたい関数である。名前をex2とした
```
つぎがex1関数（処理の中核です）
```
const ex1=(res,rej)=>{				//ex1関数は2つの引数（res, rej）を受け取る。resとrejもまた関数であり、ex1関数の中で実行される。
  setTimeout(() => {
    console.log("hello");
    res("ok");						//res関数を実行するとPromiseは成功（fulfilled）状態,rej関数を実行するとPromiseは失敗（rejected）状態になる。
									//resとrejは引数に値（例えばメッセージやデータ）を取る。この値をmesとするとmesは.then()や.catch()の引数に渡される。
  }, 2000);
}
```
最後がex2関数（thenメソッドの中で実行されるやつです）
```
const ex2=(mes)=>{					//ex2は関数、P1のメソッドである.then()や.catch()の引数に渡される関数
  console.log("then"+mes);			//ex2関数の引数にはmesがわたってくるのでex2関数内で使える。
}
```




以下は上をまとめたpromiseの簡単なサンプルです。
```
const ex2=(mes)=>{					//ex2はPromiseインスタンスのメソッド  console.log("then"+mes);			//引数にはmesがわたってくる。
}

const ex1=(res,rej)=>{				//ex1関数は2つの引数（res, rej）を受け取る。
  setTimeout(() => {
    console.log("hello");
    res("ok");						//resとrejもまた関数であり、ex関数の中で実行される。
									//res関数を実行するとPromiseは成功（fulfilled）状態,ej関数を実行するとPromiseは失敗（rejected）状態になる。
									//resとrejは引数に値（例えばメッセージやデータ）を取る。この値をmesとする
									//mesは.then()や.catch()の引数に渡される。
  }, 2000);
}
const P1=new Promise(ex1)			//Promiseの正体はインスタンスである
P1.then(ex2)						//.then()も関数を引数に取る
```



 
# promiseのまとめ

	Promiseの正体はインスタンスである。引数にはexecutor関数（実行させたい処理）を取る。
	executor関数は2つの引数（resolve, reject）を受け取る。
	resolveとrejectもまた関数であり、executor関数の中で実行される。
	resolve関数を実行するとPromiseは成功（fulfilled）状態になる。
	reject関数を実行するとPromiseは失敗（rejected）状態になる。
	resolveとreject関数は引数に値（例えばメッセージやデータ）を取る。この値をmesとする
	この値（例：メッセージ）はPromiseインスタンスのメソッドである.then()や.catch()の引数に渡される。
	.then()も関数を引数に取る、この関数は成功時に実行させたい関数である。名前をex2とする
	ex2関数の引数にはmesがわたされる。
Javaで「変数の値を取り出す」の動作を確認してみた

# 概要

Javaで「変数の値を取り出す」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/var/index8.html

# 実装

以下のファイルを作成しました。
```JSample8_1.java
class JSample8_1{
  public static void main(String[] args){
    int sum;
    sum = 80 + 76 + 94;
    System.out.println("合計：" + sum);

    int average;
    average = sum / 3;
    System.out.println("平均：" + average);
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample8_1.java 
$ java JSample8_1 
合計：250
平均：83
```

# まとめ

何かの役に立てばと。
EVM Smart Contract Development Random Tips

## Testing
1. Pattern for testing lens against mutative version function

https://x.com/0xbakuchi/status/1791473746085298532

2. Heuristic Invariant/Property in finance apps

https://x.com/0xbakuchi/status/1724803350066319661
 
2. Compiling contracts faster with `forge-std::deployCode` or `forge-std::deployCodeTo`

https://x.com/0xbakuchi/status/1778742889478242374

## Gas Optimization

1. Storing callback data on transient storage might be chapter than passing data to callback function

    Example: [metapool-router #246](https://github.com/napierfi/metapool-router/blob/601f8b0e5e5c0627d72f200e969a798afb444ebe/src/MetapoolRouter.sol#L246)

2. Replace `JUMPI` with opcode for failure pattern
Imagine if-else branch like `if condition, then revert`, the `JUMPI` can be replaced with `mload(condition - 0x01)`. The similar optimization can be seen in [mega-dropper](https://github.com/sambacha/mega-dropper/blob/main/src/ETHDropper.huff).

https://x.com/0xbakuchi/status/1797716539279573396

## Deployment

1. Crunch CREATE2 salt on terminal

https://x.com/0xbakuchi/status/1778502335901351980

2. Library to deploy contracts built by Hardhat with Foundry

https://x.com/0xbakuchi/status/1776310515221873063

3. Recording git commiet on-chain will make it easier to find version of upgradable contract

https://x.com/0xbakuchi/status/1615310839267090433
[UE5]プロパティ CallFunc_GetPlayerCharacter_ReturnValue の読み取りを試行するためのアクセスはありません。の解決例

## 何があった？

`Get Player Character`に関するロジックを少し修正したら下記のエラー文が出ました。

```:エラー文
PIE: Error: ブループリントランタイム エラー:"プロパティ CallFunc_GetPlayerCharacter_ReturnValue の読み取りを試行するためのアクセスはありません"。 ノード:  Set Actor Rotation グラフ:  EventGraph 関数:  Execute Ubergraph BP Boss Slime ブループリント:  BP_BossSlime
```

## 原因

`Get Player Character`が到達しないロジックに使用されていたためでした。

※`Get Player Character`の結果を他で使わなくても、記述するなら必ず到達させる必要があるみたいです。


## 解決した方法

必ず到着するロジック（Event Begin Play など）につなげることで、エラーが出なくなりました。
Ubuntuインストーラの画面色が黄色になるときの対処法

この記事では、Ubuntu22.04インストーラの画面色がおかしくなる際の対処法を説明していきます。

## 原因
自分なりに検索してみたところ、
Waylandが無効になっていることが、
原因だと分かった。

## 対処法
最初の言語選択の画面で、
Ctrl+Alt+Tでターミナルを開き、
下記のコマンドを実行する
```bash:
sudo gedit /etc/gdm3/custom.conf
```
そして7行目ぐらいの、
```bash:
waylandenable=fulse
```
のfulseをtrueに変更する
命名規則とLaravel

# 命名の種類について
おさらい。
単語の区切りかたによって、いくつかの名前がついている。

## camelCase / キャメルケース
- 単語の区切りを大文字で表現
- 先頭が小文字
- lowerCamelCase と呼ぶこともある

## PascalCase / パスカルケース
- 単語の区切りを大文字で表現
- 先頭が大文字
- UpperCamelCase と呼ぶこともある

## snake_case / スネークケース
- 単語の区切りを`_` アンダースコアで表現
- すべてのアルファベットを小文字で書く

## kebab-case / ケバブケース
- 単語の区切りを`-` ハイフンで表現
- すべてのアルファベットを小文字で書く

# 命名の傾向について（ざっくり）
- サーバーサイドでは、camelCase、PascalCaseが多い印象
- クライアントサイドでは、kebab-case が多い印象
- データベースでは、snake_case


# Laravelの命名規則について
まず、ここ数年Laravel扱っている私の個人の感想です。
1. リファレンス等、公式の情報としてまとまった記載はない（たぶん）
1. Googleとかで調べると、わりと古い情報が出てくる（バージョン6）
1. 結局どうなん？がわからない

そこで、2024-05-17に改めて調べたところ、以下のリポジトリを発見しました。
https://github.com/alexeymezenin/laravel-best-practices/blob/master/japanese.md#laravel%E3%81%AE%E5%91%BD%E5%90%8D%E8%A6%8F%E5%89%87%E3%81%AB%E5%BE%93%E3%81%86

今後は、この命名規則に従う方針で行こうと考えてます。

※以下記載があるのだが、本当にコミュニティに受け入れられているの？という点は確認していない。
> Laravelコミュニティに受け入れられた命名規則

## おまけ：URLについて
URLの構造については、Googleに習う。
https://developers.google.com/search/docs/crawling-indexing/url-structure?hl=ja

URL中に複数単語を組み合わせた文字列を使う必要がある場合、kebab-case を採用する方針。
RetNetの係数を入力依存のベクトルにする

https://qiita.com/3405691582/items/c6fa00e58181b6bb6ca5 の続きのようなメモです。
RetNetの隠れ状態を含んだ形の計算式は以下のように書けます：
```math
O_n = Q_n(\sum_{m=0}^{n}A^{n-m}K_m^{\intercal}V_m + A^{m+1}H_{-1})
```
ここで系列長$n$、次元数$d$について$n\times d$行列のQuery, Key, (及びValue)は論文中式(4)で示されているxPosへの展開$Q=(XW_Q)\bigodot\Theta$, $K=(XW_K)\bigodot\bar{\Theta}$, $\Theta_n=e^{in\theta}$がされているものとし、$d\times d$行列$A$は対角行列とします。$d\times d$行列$H_{-1}$は隠れ状態です。

論文中では係数パラメータ$A$は入力に依存しないパラメータとしていますが、ここでは入力依存の係数$A_n$を考えます。
このとき上式は以下のように書き換えられます：
```math
O_n = Q_n(\sum_{m=0}^{n}A_nA_{n-1}\cdots A_{m+2}A_{m+1}K_m^{\intercal}v_m + A_nA_{n-1}\cdots A_1A_0H_{-1})
```
ただし$A_nA_{n-1}\cdots A_{m+2}A_{m+1}$は$m=n$のとき単位行列$E$とします。

わかりやすさのために$n=3$まで展開してみます：
```math
\begin{align}
O_0&=&Q_0(K_0^\intercal V_0&+&A_0H_{-1})\\
O_1&=&Q_1(K_1^\intercal V_1&+&A_1K_0^\intercal V_0&+&A_1A_0H_{-1})\\
O_2&=&Q_2(K_2^\intercal V_2&+&A_2K_1^\intercal V_1&+&A_2A_1K_0^\intercal V_0&+&A_2A_1A_0H_{-1})\\
O_3&=&Q_3(K_3^\intercal V_3&+&A_3K_2^\intercal V_2&+&A_3A_2K_1^\intercal V_1&+&A_3A_2A_1K_0^\intercal V_0&+&A_3A_2A_1A_0H_{-1})\\
\end{align}
```

RetNetでは入力系列のチャンク毎に計算を行うことで効率化をしており、$[0,n)$の範囲のチャンク毎の計算は次のようになります：
```math
\begin{align}
O_n&=&(FV)_n + Q_nA_{n-1}\cdots A_0H_{-1}\\
F_{ij}&=&\sum_k(Q_{[0,n)})_{ik}D_{ikj}(K_{[0,n)}^\intercal)_{kj}\\
D_{ikj}&=&
\begin{cases}
0 & \text{if $i<j$}\\
1 & \text{if $i=j$}\\
(A_i)_{kk}\cdots(A_{j+1})_{kk} & \text{otherwise}
\end{cases}
\end{align}
```

$D_{ikj}$のイメージがつきづらいので$A_n$の$(0,0)$成分を$a_n$とすると$D_{i0j}$行列は以下のように書けます：
```math
D_{i0j}=
\begin{pmatrix}
1 & 0 & 0 & 0\\
a_1 & 1 & 0 & 0\\
a_2a_1 & a_2 & 1 & 0\\
a_3a_2a_1 & a_3a_2 & a_3 & 1\\
\end{pmatrix}
```
問題はこの$D_{ikj}$は系列長×系列長×次元数のサイズとなるためナイーブな方法ではメモリに乗らないことです。RetNetでは$D_{ikj}$の$k$軸を潰して$A_n$をヘッド毎のスカラーとすることで対応しています。

注意するとこの行列は以下のようなベクトル同士の行列積をマスクしたものとみなすことができます：
```math
\begin{align}
D_{i0j}&=&
\begin{pmatrix}
1 & 0 & 0 & 0\\
a_1 & 1 & 0 & 0\\
a_2a_1 & a_2 & 1 & 0\\
a_3a_2a_1 & a_3a_2 & a_3 & 1\\
\end{pmatrix}\\
&=&
\Big(
\begin{pmatrix}
1\\
a_1\\
a_2a_1\\
a_3a_2a_1
\end{pmatrix}
\begin{pmatrix}
1 & a_1^{-1} & (a_2a_1)^{-1} & (a_3a_2a_1)^{-1}
\end{pmatrix}
\Big)
\bigodot
\begin{pmatrix}
1 & 0 & 0 & 0\\
1 & 1 & 0 & 0\\
1 & 1 & 1 & 0\\
1 & 1 & 1 & 1
\end{pmatrix}
\end{align}
```
したがって
```math
\begin{align}
B_{ik}&=&
\begin{cases}
1 & \text{if i=0}\\
(A_i)_{kk}\cdots(A_1)_{kk} & \text{otherwise}
\end{cases}\\
(1/B)_{ik} &=& 1/B_{ik}\\
M &=& \begin{pmatrix}
1 & 0 & 0 & 0\\
1 & 1 & 0 & 0\\
1 & 1 & 1 & 0\\
1 & 1 & 1 & 1
\end{pmatrix}
\end{align}
```
としたとき
```math
F_{ij}=\sum_k(Q_{[0,n)})_{ik}B_{ik}(1/B)_{jk}(K_{[0,n)}^\intercal)_{kj} \bigodot M
```
のように系列長×次元数のサイズの行列の積の形で書くことができます。
$B_{ik}$は[以前の記事](https://qiita.com/3405691582/items/c6fa00e58181b6bb6ca5)で提案した対数畳み込みを用いて計算できます。

# 実装
整理してから出します
yukicoder contest 430でwriterやりました　小話など

## 挨拶
にゃ～ん

## 本題
2024/05/17に開催されたyukicoder contest 430でF,G,Hの3問のwriterをいたしました。
あと全問testerもしました。
writerをした各問についてtwitterで書いた内容よりちょっと多めに語ります。

https://yukicoder.me/contests/495

twitterに投げたやつは↓ここのツリーから見てね～

https://twitter.com/kisara_splat/status/1791474545892962367

## F Counting and Deleting
部分列の種類数を数え上げる方法は有名です。[けんちょんさんの記事](https://qiita.com/drken/items/a207e5ae3ea2cf17f4bd)によくまとまっています。
同じ文字列を重複なく数え上げるのが大事です。同じ文字を拾うとき前からできるだけ拾っていくか、後ろからできるだけ拾っていくか。というルールを決めよう。
解説に丁寧に書きましたがこれはセグ木に乗ります。行列の形で書くとわかりやすいよ。
区間変更クエリが要素 $S_i$ に対して定数回しか作用しないなら（遅延評価しない）セグ木で十分という面白要素も盛り込んだけど、軽い構造体にしたり高速な言語を使ったりで遅延セグ木でも通る。おこ(# ﾟДﾟ)
愚直がありえないくらい早い vs 行列がありえないくらい重い
TLは4 secsですが、愚直でも10 secsあると通ってしまいます。これでもpython系は少し割を食う制約です。
愚直は↓こんな感じのコードになります。

```cpp:brute_force.cpp
mint query2(int l, int r){
	mint f = 0;
	mint g = 0;
	for(int i = l; i <= r; i++){
		if(s[i] == '0') f = f + g;
		if(s[i] == '1') g = f + g + 1;
	}
    return f + g;
}
```

どこかで見たことある気がするけど見つからない……もしや未出？　と思ったらちゃんと既出でちゃんと解いたことあった。

https://atcoder.jp/contests/abc246/tasks/abc246_h?lang=ja

20人解いてくれました。行列に帰着しないと構造体作るのめちゃ苦しいよね～！

## G Macaron Gift Box
問題の内容は同値ですが、初期段階ではこんな感じで考えていました。

> 次の等式を満たす $0$ 以上 $K$ 以下の非負整数から成る列 $(x_1,x_2,\ldots x_N)$ は何通りありますか。
> $$\sum_{i=1}^N ix_i = N$$


コンテスト1週間前にTLでこちらのツイートをみたとき血の気が引きました。ひゅいっ……！

https://twitter.com/nouka28/status/1788159280061067729

よく考えると違う方針で解かなきゃいけないのでセーフ。こちらは分割統治（誤用？）FFTとBostan-Moriの合わせ技だね～

問題に戻ります。exp-log典型のやさしめの問題を出したかったです。知らなくても「分割数」などから検索で辿り着けてくれたらうれしいなという気持ちがあったので、かなりシンプルな形で出題させてもらいました。
あとオイラーの五角数定理さんも忘れないであげてね。
個数制限付き分割数（？）とでも呼ぶべき問題ですが分割数列挙+畳み込み一撃だけで解けるの面白くないですか？

次数の小さい方からFFTしていくやつがABCでついこの前に出題されたので、次はexp-log典型が近いうちに出てくるのではないかと睨んでる。こいつら見た目が似た形で出題されるのでセットで覚えちゃおう！

25人解いてくれました。やっぱ人々FPS強いな～

## H Warp Drive Spacecraft

 $O(N^2)$ 辺ある最短経路問題を問題の性質に注目して考える辺を減らす、という類の問題。実は半年くらい原案を温めてきた問題です。最近Convex Hull Trickも出題されてないしこれはきっと受けいいぞ～(^^♪
コンテスト1週間前の土曜日

> [ABC353-G Merchant Takahashi](https://atcoder.jp/contests/abc353/editorial/9984)
> $O(NQ)$ 辺ある最短経路問題です。
> CHT で解けます。

そんな……( ´◔ ‸◔`)。

ポンポンとテスターさんが見つかるなら手元の他の問題との差し替えてようとも思ったのですが、twitterで募集かけてみると厳しそうだったのでそのまま出題。悲しいね

軽いワープと重いワープをいくつか候補にいれてDijkstraする嘘解法が実は通ってしまいました。
自分もtesterさんも思いつかなかったなら仕方ないよな……学びを得たので次に生かしたい

結構面白い問題になったと思ってるよ！　ぜひ解いてね！

22人解いてくれました。ぼくは2時間で解ける気がしません。すげ～

## 難易度評価
HはFとGと比べて6,7割のAC数だろうと思ったけどF,G,Hの3問ともAC数ほぼ横並び。
あと全問testerしてたのですがB,Cは☆0.5個分プラスすべきだったのか。
難易度評価は本当に難しいですね……

## おわり

原案のストックはあるのでまた出題したいなの気持ち。共催してくれる人いたらいつでも声かけてください。
あとtester募集を見かけたら積極的に凸ってあげようと思った。
Excelワークシート関数: _forAllAdjPair -- 関係演算子をリスト全体に適用する

2024年5月18日

Scheme の ``(< 1 2 3 4 5)`` のように、関係演算子を順に適用した結果の論理積を求めるような Excel ワークシート関数 ``_forAllAdjPair`` を作ってみた。

## ``_forAllAdjPair`` 関数

<table>
<tr><td>第1引数<td>関係演算子（関数）を指定する。
<tr><td>第2引数<td>配列（関数で生成した配列でもいいし、ワークシート上のセル範囲でもいい）を指定する。
<tr><td>評価値<td>第1引数の配列を <code>TOCOL</code> で1次元にしたリストで、隣接するデータを関係演算子に当てはめて、その結果の <code>AND</code> がこの関数の値である。比較するデータの個数が2個未満の場合は <code>#N/A</code> になる。
</table>

```
=LET(
  _forAllAdjPair,
    LAMBDA(_関係演算子,_データ配列,
      LET(
        _データ配列_直列, TOCOL(_データ配列),
        IF(ROWS(_データ配列_直列)<2,
          NA(),
          AND(
            BYROW(
              HSTACK(
                DROP(_データ配列_直列, -1),
                DROP(_データ配列_直列,  1)),
              LAMBDA(_r, _関係演算子(INDEX(_r,1,1), INDEX(_r,1,2)))))))),

  _forAllAdjPair関数を使う数式をここに書く
)
```

``SEQUENCE`` 関数を使う別バージョンも...（こっちの方が高速かも？）

```
=LET(
  _forAllAdjPair,
    LAMBDA(_関係演算子,_データ配列,
      LET(
        _データ配列_直列, TOCOL(_データ配列),
        _データ配列_個数, ROWS(_データ配列_直列),
        IF(_データ配列_個数<2,
          NA(),
          AND(
            MAP(SEQUENCE(_データ配列_個数-1),
              LAMBDA(_i,
                _関係演算子(
                  INDEX(_データ配列_直列, _i),
                  INDEX(_データ配列_直列, _i+1)))))))),

  _forAllAdjPair関数を使う数式をここに書く
)
```

## 使用例: 数値配列のすべての値が同じであることを確認する。

``_関係演算子`` として ``LAMBDA(_x,_y, _x=_y)`` を指定する。（``=`` の代わりに ``EXACT`` を使えば文字列リストでもこれが使える。）

```
=LET(
  _forAllAdjPair,
    ～上記の定義～,

  _forAllAdjPair(LAMBDA(_x, _y, _x=_y), {3.14, 3.14, 3.14, 3.14})
)
```

## 使用例: 数値配列が昇順であることを確認する。

``_関係演算子`` として ``LAMBDA(_x,_y, _x<=_y)`` を指定する。

```
=LET(
  _forAllAdjPair,
    ～上記の定義～,

  _forAllAdjPair(LAMBDA(_x, _y, _x<=_y), {1, 1, 2, 3, 5, 8, 13, 21, 34})
)
```
5/18 tecHub（LT＋懇親会）を開催しました！

![5_18tecHub①.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/a1586ab3-69f8-db81-9ee0-f044d77859d4.jpeg)

「社内研修、意外と長い」

「初任給、入りました」

学生から社会人になり、生活の変化に慣れるのに大変な1ヶ月だったと思います。また、OJTを通して仕事を覚えている人もいると思います。

今月のtecHubは、LT付きの懇親会を開催しました。
tecHubでは、ITエンジニアという仕事だけでなく、仕事とプライベートも考えてキャリアアップの相談ができます。

今回は、初任給の使い道について興味深い話を紹介します。

**目次▼**
<INS>[今月のトピック](#今月のトピック)
[2024年5月のtecHubを開催しました！](#2024年5月のtecHubを開催しました！)
[今後について](#今後について)
[次回の開催](#次回の開催)</INS>

<h3>今月のトピック</h3>
「初任給、何に使いますか？」

家族にプレゼントを買う、自分へのご褒美を買う。使い方は様々だと思います。

今月のトピックは、初任給の使い道です。2023年の初任給の使い道の第一位は「貯蓄」でした。

さて、今年は変化がありました…！

<b>【2024年】初任給の使い道</b>
今年のランキングは以下になります。

<b>１位　趣味</b>
<b>２位　家族へのプレゼント</b>
<b>３位　貯金</b>

1位は趣味ですが、2位は家族へのプレゼントでした。
今まで育ててくれた感謝の気持ちをプレゼントする人が多いです。

<b>ただし手元に残った額に不安。生活に余裕が無いとの回答も多数</b>
趣味やプレゼントに充てる中で、手元に残った額に不安を覚える人も多いようです。
どんどん物価が上がっていく今の日本では、生活に余裕が無いと感じるのは当たり前かもしれません。

生活費の余裕を作るには、節約するか、収入を上げるかです。
節約だけでは限界があるので、若いうちから収入を上げるのも重要だと思います。

今の日本は、転職をキャリアアップの一つの手段として捉え、人生設計を長期で考える時代です。
tecHubでは、そういう方に向けてリアルな情報交換の場を提供しています。

<h3>2024年5月のtecHubを開催しました！</h3>
5/18にtecHubを秋葉原で開催しました。
参加者は、61名となり、大盛況でした。

日付：5/18(土)　13:00～16:30
場所：ワイム貸会議室お茶の水 RoomB
参加者：61名
内容：一部：LT、二部：懇親会

<b>tecHubは毎月イベント開催しています！</b>
毎月60〜80名ほどの方が参加している人気のイベントです。

3ヶ月に1度：LT（ライトニングトーク）と懇親会の2部構成イベント
その他：オフラインのIT交流会イベント

LT＋懇親会では、前半は「働き方」をテーマにLT、プレゼンテーションを、後半は懇親会で自由に交流の時間を設けています。
LTでは、外部スピーカーをゲストに招くこともあります。

懇親会にはプレゼンターも参加し、発表内容をさらに掘り下げてディスカッションをすることも可能です！ いろんな立場の方が自由に意見・情報交換をできる場となっています。

![5_18tecHub②.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/d2b5a413-7b43-ab90-05f7-c25db5b0669b.jpeg)

<h3>参加者の声</h3>
今回も、参加者は幅広い分野のIT関係者が集まり会社員からフリーランスエンジニア、法人化されている人まで様々な人が参加していました。

今月のLTでは、スピーカーの経験を通したキャリアアップの話でした。会社員からフリーランスへ。そして起業するまでの体験談は、濃厚で学びが多かったです。変化の多い今の時代にマッチしたキャリアアップの話だったので、多くの参加者から参考になったという声を聞いています。

tecHubは、今後も毎月イベントを開催していきます。
他にもITエンジニアがより活躍し、理想のキャリアを切り拓けるように新たな取り組みをしていく予定です。
今後もtecHubをよろしくお願いいたします。

<h3>次回の開催</h3>
次回の開催は以下の日程を予定しております。

日時：6/15(土)　14:00～16:30　
場所：LIFORK秋葉原Ⅱ1階ラウンジ
内容：IT交流会
詳細とお申込みは以下をご確認ください。

https://www.navi56.com/communities/tecHub

※イベントの申込みにはコミュニティに参加が必要になります。tecHubコミュニティに参加後にサイト内の"イベント検索"から「6/15tecHub（交流会）」を検索してお申込みください。