OmniAICreator/Qiita-1.07M huggingface dataset:
PuLPで線形計画問題を解く

# 初めに
Pythonと高校数学をある程度理解していると学びやすいかと思います。
また環境として _Jupyter Notebook_ を想定しています。
## PuLPとは
数理最適化問題を解くためのPythonライブラリです。
## 線型計画問題とは
線形計画問題とは、下記例題のような目的関数と制約条件が１次式で表される最適化問題です。今回は下記例題について考えています。

__例題__
不等式x≧0, y≧0, x+3y≦10, 2x+3y≦11, 2x+y≦9をすべて満たす領域を _D_ とするとき，領域 _D_ におけるx+yの最大値を求めよ．
つまり、下図の領域 _D_ の中で、x+yの最大値を考えたい。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984252/0ff0bca7-b7f0-2615-fbba-e2d44af62662.png" width="400">


## インストール手順
```
! pip install pulp
```

# 解法手順

## 数理モデルの定義
```python
import pulp
problem = pulp.LpProblem('LPP', pulp.LpMaximize) # 最大化
```
第１引数については任意の名前でよいので、線型計画問題(linear programming problem)からLPPとしています。
第２引数では最大化問題と定義しています。同じように最小化問題を解きたい場合は、下記で実行できます。

```python
problem = pulp.LpProblem('LPP', pulp.LpMinimize) # 最小化
```

## 変数の定義
例題には２変数xとyがあるので定義します。
```python
x = pulp.LpVariable('x', cat='Continuous')
y = pulp.LpVariable('y', cat='Continuous')
```
変数xとyを定義します。
こちらも第１引数は任意の名前でよいので、そのままxとyとします。
第２引数の __cat='Continuous'__ については、xとyが連続値であることを定義しています。

## 制約条件の定義
例題の制約条件を書き下すと
① x≧0
② y≧0
③ x+3y≦10,
④ 2x+3y≦11
⑤ 2x+y≦9
となるので、これらを一つずつ定義していきます
```python
problem += x >= 0               #➀
problem += y >= 0               #➁
problem += x + 3 * y <= 10      #➂
problem += 2 * x + 3 * y <= 11  #➃
problem += 2 * x + y <= 9       #➄
```
__+=__ を用いて、problemに制約条件を追加していきます。
右辺の制約式を見ると、boolen型になっているように見えますが、制約式として追加されています。

Pythonのコードとしてはかなり戸惑う部分が多いと思いますが、数学としては直感的で分かりやすいかと思います。

## 目的関数の定義
```python
problem += x + y
```
problemの目的関数を定義します。
制約式の定義と似ていますが、__+=__ の右辺が関数の形になっています。
この形で違和感がある場合は、下記の２つの書き方でも同じように定義することができます。

```python
problem.setObjective(x + y)
problem.objective = x + y
```

## 数理モデルを解く
実際に解いていきますが、上記条件で解が求まるかを確認します。
```python
status = problem.solve()
print(pulp.LpStatus[status])
```
１つの解が求まっていれば、Optimalと出力されます。

では、実際に解を見てみると、
```python
print('x=', x.value(), 'y=', y.value(), 'の時、最大値', x.value()+y.value())
```

```
x= 4.0 y= 1.0 の時、最大値 5.0
```

と一つの解が求まっています。

# まとめ
```python
#数理モデルを定義
problem = pulp.LpProblem("LCC",pulp.LpMaximize)

#変数を定義
x = pulp.LpVariable('x', cat='Continuous')
y = pulp.LpVariable('y', cat='Continuous')

#制約条件を定義
problem += x >= 0               #➀
problem += y >= 0               #➁
problem += x + 3 * y <= 10      #➂
problem += 2 * x + 3 * y <= 11  #➃
problem += 2 * x + y <= 9       #➄

#目的変数を定義
problem += x + y

#数理モデルを解く
status = problem.solve()
print(pulp.LpStatus[status])
print('x=', x.value(), 'y=', y.value(), 'max=', x.value()+y.value())
```

今回は実施していないが、求まった解が制約条件を満たしているかは検証するべきだろう。
[Swift]タイプライター風にUILabelをアニメーションさせる

# 参考動画
![-gdjupqclrgqq32do.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643372/1a7a2107-61b2-62d4-fb63-f71d0cceb873.gif)

このようにUILabelを1文字ずつ表示するアニメーションをする方法を紹介します。

# コード
```.swift
final class View: UIView {
    @IBOutlet weak var label: UILabel!
    private var timer = Timer()
    private var currentTextCount = 0
    var text: String?

    private func setTimer(_ text: String) {
        timer = Timer.scheduledTimer(timeInterval: 0.075, target: self, selector: #selector(textAnimation(_:)), userInfo: text, repeats: true)
    }

    @objc private func textAnimation(_ timer: Timer) {
        guard let text = timer.userInfo as? String else {
            return
        }
        label.text = String(text.prefix(currentTextCount))
        
        if text.count <= currentTextCount {
            timer.invalidate()
            return
        } 
        currentTextCount += 1
    }
}
```

# 解説
`text`に対して、先頭n文字をTimerで設定した0.075秒間隔で取り出して表示しています。（参考動画はGIFなので遅め）
この処理はUILabelだけではなく、`UITextView`でもできます。

他のアクションでアニメーションを止めたい場合は`invalidate()`で停止できます。

```
// タイマーを止める
timer.invalidate()
```
テーブルを作ろう！

こんにちは！
今日はデータベースにデータを格納するためのテーブルを作成します。とても簡単ですので拍子抜けな感じはすると思いますけれど、私たちとしてはぜひ拍子抜けしていただきたいところです。

# テーブル定義のSQL
Vantageでテーブルを作成するときの最低限必要なSQLは下記のとおりです。

```SQL:Create_Table.sql
Create Table [データベース名またはユーザー名].[テーブル名]
(
   [カラム名] [データ型],
   [カラム名] [データ型],
         ・・・
   [カラム名] [データ型]
)
Primary Index
(
   [カラム名]
);
```

実際の例にするとこんな感じになります。

```SQL:Create_Table.sql
Create Table User_A.Table_A
(
   Col_1 Integer,
   Col_2 Varchar(20),
   Col_3 TimeStamp
)
Primary Index
(
   Col_1
);
```

シンプルでしょ？シンプルだと思いませんか？
これで並列機能を存分に活用して大きなサイズのデータも高速で処理できるテーブルの出来上がりです。

もちろんより高速にデータを扱うためのパーティション・プライマリ・インデックスを定義したり、テーブルをカラムナー型にしたりなどいろいろな機能を活用する場合は追加のキーワードが必要になりますが。
そういった機能はこのあとリンクに示すマニュアルを参照してみてください。

また利用できるデータ型ももっとたくさんあります。JSONデータをテーブルに持つこともできますし、なんならデータ型をユーザーが定義することも可能です。
こちらもマニュアルの方を参照してみてください。新しい発見があるはずです！

# より詳しい情報はこちら
[Teradata Vantage™ - SQLデータ定義言語 構文規則および例 テーブル文](https://docs.teradata.com/r/1I0dmX0LSNZgNE0umobdwQ/cdJYl3UkthkZN8cgHbXQSQ)
[Teradata Vantage™ - SQLデータ定義言語 詳細トピック CREATE TABLE(グローバルおよび一時)](https://docs.teradata.com/r/7IqmsKx4YhvVMZd6Ca~pPw/8otVykAXFAQ5pNS1s0kERQ)
[Teradata Vantage™ - SQLデータ定義言語 詳細トピック CREATE TABLEオプション](https://docs.teradata.com/r/7IqmsKx4YhvVMZd6Ca~pPw/n5Fk6xDAJJ1RUVrWZF7~8Q)
[Teradata Vantage™ - データ タイプおよびリテラル](https://docs.teradata.com/r/n8oDHGbNQKDBZnoZKIujQA/root)

#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
O'REILLY の『Go言語でつくるインタプリタ』が良かったので、続きの洋書『WRITING A COMPILER IN GO』 もやってみた

この記事は [Go Advent Calendar 2022](https://qiita.com/advent-calendar/2022/go) カレンダー 2 の 21 日目の記事です。

『WRITING A COMPILER IN GO』という書籍を読んでコンパイラを作ってみたので、その書籍について紹介します。

## 『Go言語でつくるインタプリタ』と『WRITING A COMPILER IN GO』について

まず、『Go言語でつくるインタプリタ』については、
O'REILLY から 2018 年に日本語訳版が発売されたものとなります。  

書籍で想定したオリジナルの言語 `Monkey` のインタプリタを実装していくという内容になっています。 
ステップバイステップで少しずつ作っていく流れがわかりやすく、私も楽しくインタプリタの作成を実践することができました。

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

そして、今回紹介する書籍は『WRITING A COMPILER IN GO』というタイトルのもので、  
こちらも、上記のインタプリタ本と同じ、Thorsten Ball さんが執筆された書籍となっています。  
こちらは、2022 年 12 月現在は、まだ日本語訳版は発売されていおらず、オリジナルの洋書のみが販売されています。  
書籍は電子、ペーパバックどちらも Amazon から購入することができます。

https://www.amazon.co.jp/Writing-Compiler-Go-Thorsten-Ball/dp/398201610X

内容は、上記のインタプリタに対しこちらは同じ `Monkey` のコンパイラを作成するという内容になっています。  

本記事では、『WRITING A COMPILER IN GO』読み、コンパイラを作成してみたことを振り返って、  
簡単にこの書籍でどのようなことを学べるかを紹介したいと思います。  

## インタプリタ版とコンパイラの違い

インタプリタ版とコンパイラ版の違いは以下の図のようになります。  

一言で言うと、インタプリタ版では主にコンパイラフロントエンドについて学ぶのに対して、  
コンパイラ版は主にコンパイラバックエンドについて学ぶ内容になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143910/6fb6b5e4-f62a-cd7f-73a7-2166b46c5032.png)

## コンパイラ版で学べたこと

コンパイラ版を実際にやってみて、学べたことは以下です。  
内容がコンパイラバックエンド側に集中しているため、以下をじっくり学べるようになっています。

* マシンコードとそれを実行する環境が作成できる
  * VM 用の簡単な命令セットの実装ができる
  * 命令セットを実行する簡単な仕組みの VM を実装できる
* コンパイラバックエンドの具体的な処理を実装できる
  * AST を再帰的に解析して、命令とオペランドのバイトコード(マシンコード)へ変換する処理が実装できる
* 上記の仕組みの中で様々なプログラミング言語の機能を実現する方法を学べる
  * if 文や Closure などプログラミング言語の機能を実際にコンパイラ～ VM で実現する方法がわかる

## まとめ

Thorsten Ball 氏の、「読者と一緒になって考えていく」スタイルの構成のおかげで、インタプリタ版に引き続きわかりやすくてよい書籍だと思いました。  
コンパイラ本からいきなり読んでみてもよいと思いますし、インタプリタ本からやるとなおよいと思いました。  

洋書しかまだ販売されていないため、英文を読む必要があるのがややハードルとなりますが、  
特別な英語のスキルのない私でも、辞書を引きながら読めば挫折しない程度には読むことが出来ました。

## References

* [Go言語でつくるインタプリタ Thorsten Ball 著 設楽洋爾 訳](https://www.oreilly.co.jp/books/9784873118222/)
* [WRITING A COMPILER IN GO Thorsten Ball 著](https://www.amazon.co.jp/Writing-Compiler-Go-Thorsten-Ball/dp/398201610X)
C++ で ULID 生成

# はじめに
はじめまして、らくだです。

今回が初の投稿になるので、見づらいと思います。
どうか、ご容赦ください。

今回、記事を投稿するに至ったのは、「c++でulid生成」を紹介する日本語の記事が見当たらなかったので、参考になればと思ったからです。

ちなみに、c++でのulid生成に絞って紹介しますので、ulidがどのようなものかについては、ほかの記事をあたってください。

今回、参考させていただいた記事↓
ulid/c++
https://github.com/suyash/ulid
ミリ秒単位の経過時間取得
https://www.delftstack.com/ja/howto/cpp/how-to-get-time-in-milliseconds-cpp/

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [gitからコピペ](#Chapter1)
1. [重要](#Chapter2)
1. [実行](#Chapter3)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# gitからコピペ


まず、実行用のディレクトリ配下に、
下記のurlから2つのファイルをコピぺします。
https://github.com/suyash/ulid

コピペするファイルは、
ulid_struct.hh
ulid.hh

コピペでなく、クローンしてもらっても構いません。
今回は、二つだけ使わせてもらうので、コピペにしました。
<a id="#Chapter3"></a>
# 重要
ここからは、投稿主が実際にはまった場所です。

先ほどコピペしたファイルの、ulid_struct.hhではtime_tという型が使われています。どうやらこいつが、主の実行環境では31bitなようで、ulidは最初の48bitがtimestampなので、シフト演算のbit数が超過しておかしな値になります。
これを解消するために、ulid_struct.hh内のtime_t型をすべてlong long型にします。（uint64_tでも構いません）


<a id="#Chapter2"></a>
# 実行

実行用「ulid.cc」ファイルを同じディレクトリに入れます。

test
　├ ulid_struct.hh
　├ ulid.hh
　├ ulid.cc

ulid.ccを以下のコードに変更
```c++:ulid.cc
#include "ulid.hh"
#include <iostream>
#include <chrono>
#include <random>

using std::cout; using std::endl;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
using std::chrono::seconds;
using std::chrono::system_clock;

std::string ulid_s(void){
    //ミリ秒単位の経過時間
    long long now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();

    //第二引数：0~255範囲の乱数を生成する関数
    ulid::ULID ulid = ulid::Create(now, []() { return rand() % 256 - 1; });
    std::string str = ulid::Marshal(ulid);

    std::cout << str << endl;

    return str;
}

int main(void){
    
    srand((unsigned int)time(NULL));
    
    ulid_s();

    return 0;
}
```

以上で終了です。

実行してみますと
```
01GMSM5HFF70YG5AC3F8T9EVPQ
```
このような値が出ます。

ちなみに、ulid::Createの引数を(1484581420, []() { return 4; })にすると
```
0001C7STHC0G2081040G208104
```
このような値が出ます。

いかがでしたでしょうか。
探り探りでやったので、間違いがあるかもしれません。
見つけましたら、コメントよろしくお願いします。

ソースコードをみて、各関数がどのような動きをしているのか見てみるのも面白いと思います。

それでは、今回はこのあたりで失礼します。

<a id="#reference"></a>
# 参考URL
- [https://github.com/suyash/ulid](URL)
- [https://www.delftstack.com/ja/howto/cpp/how-to-get-time-in-milliseconds-cpp/](URL)
ラムダ式を勉強する

abstract methodを１つだけもつインタフェース。
new with implementして、overrideする。

Comparator#compareをoverride
```java
    public static void main(String[] args) {
        Comparator<String> c = new ComparatorImpl();
        System.out.println(c.compare("ABC", "DEF"));
    }
    static class ComparatorImpl implements Comparator<String> {
        public int compare(String s1, String s2) {
            return s1.compareTo(s2);
        }
    }
```
```
-3
```
ラムダ式を使う。
Comparatorのabstract methodはcompareの1つのみのため、
メソッド名compare, argument type, return,new を省略する。
残るのはargs、method contentのみ
```java
    public static void main(String[] args) {
        Comparator<String> c = (s1,s2) -> s1.compareTo(s2);
        System.out.println(c.compare("ABC", "DEF"));
    }
```
```
-3
```
夫婦でスクラムチーム組んでみた話

## はじめに

私事ではありますが、今春、第一子となる男の子が誕生しました。
それはそれは可愛く、短いながらも育休も取得し、育児や家事にも積極的に参加してきました。

**が！、** 世の中には産後クライシスという言葉があるように、出産を期に夫婦間の仲が急激に冷え込んでしまう現象があるようです。
我が家も例に漏れず、子育てに関する方針の違いや小さいことから喧嘩になってしまうことが増えてしまっていました。（産後クライシスというほどのものでも無いですが、、）

この状況を打破すべく、1年前に取ったスクラムマスターの資格から得た知識や考え方を生かせないかと考え、いろいろとやってみました。
本記事ではその試行錯誤を紹介しようと思います。

## 何をやったか？

スプリントプランニング、プランニングポーカー、デイリースクラム、ペアプログラミング、スプリントレビュー等々、スクラム開発におけるフレームワークは多岐にわたって存在しています。これらをすべてやるのは時間的にも難しく、長続きしないだろうと考え以下の３つに絞ってやってみました。
* プロダクトバックログ
* デイリースクラム
* レトロスペクティブ

実際にやったこととその効果を紹介していきます。

## プロダクトバックログ

子供が生まれてから、予防接種はいつ行くか、離乳食の準備はいつから始めるか、等々の夫婦で協力して解決すべき事項が激増しました。
これに加えて個人的な用事（散髪とか仕事に関すること等）も、子供の存在があるので勝手に時間を決めて一人でやるわけにはいかなくなり、どうしても協力して行っていく必要が出てきたのですが、実際には、これらのような夫婦間におけるやる必要があることの認識の統一ができておらず、共通の問題意識が持てていないという問題が発生してしまっていました。

この問題を解決すべく、プロダクトバックログの管理、つまりは**生活するうえで必要となるタスクの可視化と共有**をどうにかしてうまくできないかやってみました。

### 実際にやったこと

上述したようなタスクを管理するために、[Trello](https://trello.com/ja)というタスク管理ツールを導入しました。
このツールではリストとその中に紐づけるカードを作成することができます。カードは容易に移動することができ、このツールを夫婦共同で管理するようにしました。
下図はその中の一つ、買い物リストのボードになっています。(余談ですが、[IFTTT](https://ifttt.com/)を活用し、alexaに買い物リストの追加をお願いするだけで自動的にこのリストに追加されるように設定しています)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168722/a7ef8b4c-9e4d-6579-d656-22b8ed894e85.png)
この手法の導入により、家族内におけるタスクが可視化され、役割分担がスムーズに進むようになり協力してタスクに取り組むことができるようになりました。

## デイリースクラム

プロダクトバックログに記載したタスクのうち、今日何をやるかを決めるためにデイリースクラムを実施するようにしました。
極力朝食を同じ時間に取るようにし、その間にそれぞれが実施するタスクをTrelloを見ながら決定します。
また、スプリントプランニングのようなプロダクトバックログを出す時間が存在しないため、このデイリースクラムの時間で思いつくものをどんどん追加するようにしています。

## レトロスペクティブ

現在、私はほとんどを自宅からテレワークで勤務している状態で妻とは四六時中一緒にいる状態となっています。
そんな中で口に出すほどではないけど、どうしても感じでしまう小さい不満というものはお互いにたまるもので、それが積もり積もって表に態度として出てしまう…ということが何度かありました。

このような状態を解消すべく、定期的に話し合いの場を設ける意味を込めて振り返りの場を導入しました。

### 実際にやったこと

1週間に1回、子供が寝た後に[Miro](https://miro.com/ja/)を使っての振り返りの場を設けるようにしました。
KPTの形で実施し、下図のようによかったこと、悪かったことをどんどん書いていきます。
お互いにそれらを共有した後に、トライしたいこと、翌週に実際にやることを決めていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168722/1371f3eb-cf82-eb37-9f9c-c14c287e1458.png)

これによりお互いにどんなことに不満を感じて生活しているのかを共有する場ができ、不要な争いが明らかに減少しました。
また、話し合って改善する機会を意図的に設けることで、お互いに夫婦というチームを成長させていこうという認識ができたので、非常に良い取り組みだったと感じています。

## 終わりに

夫婦間にスクラムにおける3つの考え方を当てはめて実際にやってみました。
この中でも特にレトロスペクティブは有用であったと思っています。
**話し合うということを当たり前にする**ことが夫婦というチームの成長のカギなのではないかと思います。
皆さんも是非試してみてはいかがでしょうか？
非技術者がJavaScriptフレームワーク・ライブラリの違いを調べてみた

技術研修を提供しているカサレアルでは、JavaScriptのフレームワーク、ライブラリを学ぶコースをいくつか用意しています。
お客様から研修のご要望を伺う際、「JavaScriptフレームワークのおすすめどれですか？」と相談を受けることもあります。

JavaScriptが何かは分かっているものの、数多のJSフレームワーク、ライブラリの違いって何だろう？
いや、そもそもフレームワークとライブラリの違いは？と疑問があったので、調べてみました。

## フレームワークとライブラリの違い

フレームワークはWebアプリケーションの
・骨組み
・土台
・ひな形
・設計を再利用でき効率化するもの

ライブラリはWebアプリケーションの
・部品
・汎用性の高いパーツのコレクション
・コードを使い回し効率化を可能にしたもの
・開発効率を上げプログラムを軽くするもの

あらゆるサイトで調べ、色んな表現が出てきました。

ですが、調べてみると、どれがフレームワークでどれがライブラリなのかという解釈は、人それぞれのように感じました。
というのも、カサレアルではReactやVue.jsをライブラリと紹介していますが、
調べたサイトによってはフレームワークだと書いてる人が結構いたからです。
（Angular、React、Vue.jsで「3大フレームワーク」と呼ぶ記事もよく見ました。）

個人的にフレームワークとライブラリの違いを理解しやすかったのは、下記のサイトです。
https://zenn.dev/nameless_sn/articles/framework_and_library

この記事に書かれたコメントまで読んで、なんとなくニュアンスを掴めました。

## JavaScript「3大フレームワーク」の違い

3大フレームワーク（Angular、React、Vue.js）はカサレアルでも入門編から研修提供しています。
2020年～2022年の3年間、Angular、React、Vue.jsの中で、
カサレアルでの受講者数はReact、Vue.jsは年々伸び、Angularのみ減少傾向にあります。

この点に関しては、受講者アンケートから分析したトレンド比較を2022年の夏に講師が講演したことがあります。
講演動画はYoutubeに上がっていて、非技術者の私が見ても分かりやすくまとまっているので、おすすめです。
11:30～あたりからはじまります。
https://youtu.be/YGCoJEq3j7Y?t=690


そして、3大フレームワークそれぞれの特徴を、非技術者でも理解できる範囲で調べました。
参考：https://www.kagoya.jp/howto/

#### ★Angular
・Angular単体で開発可能なフルスタックフレームワークである
・Typescriptの学習が必須になる
・あらかじめNode.jsのインストールが必要
#### ★React
・1つの開発環境でWebアプリのみならず、スマートフォンアプリも開発可能
・独特な記述方式や抽象的な概念が多く、理解に時間がかかり、学習コストは高め
・あらかじめNode.jsのインストールが必要

#### ★Vue.js
・シンプルな設計で柔軟性が高く、他ライブラリと組み合わせて使うことも可能
・日本語のドキュメントが豊富で学びやすい
・大規模な開発には向かない
・あらかじめNode.jsのインストールが必要


それぞれメリットデメリットがありますが、
カサレアルのJavaScript研修の中で1番受講者の多いReactが学習コストが高いと知り、
難しいからこそ、独学ではなく研修会社を使って学んでいる技術者が多いのかなと感じました。

そして、3つ全てに共通して出てきました、Node.js。
カサレアルでもNode.jsの研修コースを提供していますが、今までフレームワークの1種だと思ってました。

#### ★Node.js
・JavaScriptをバックエンドで動作する為のプラットフォーム

JavaScriptはフロントエンドのプログラミング言語という固定概念を持っていましたが、バックエンドでも使える、と。
そしてNode.jsはフレームワークではなく、JavaScript実行環境とかなり異なることを理解しました。

しかし、どのJavaScriptフレームワーク・ライブラリでも使えるなら、
多くの方が身に着けるべき、3大フレームワークとセットで学ぶべき技術かと思うのですが、
弊社の受講者数は直近3年間とも特別多くはありません。
こちらは独学の方や、業務で使い慣れていく方が多いのでしょうか、気になるところです。

## まとめ
・フレームワーク、ライブラリの表現の差は個人による
・Reactは学習コストが高いので、学習のプロである研修会社を利用する方が多い（のかもしれない）

違いを学んだうえで、来年2023年のJavaScript動向も気にしてみようと思います。
pywebviewをちょっと便利に使う

# python側からjs側に作用したい
js側にファンクションを用意せずにpython側からjsスクリプトを実行したい場合、evaluate_jsでpython側からjs側に作用は出来るのですがwindowを指定する必要があるのでどこかのタイミングでAPIにwindowを渡しておく必要があります。
のでwindowをapiに渡すために以下のようにしてみます。

```python
api = Api()
api.window = ...
```
これによってApiクラスの中では```self.window```で参照することが可能になります。

※本来はjs側からAPIが呼び出されてそのレスポンスとして動作するのが正しいと思うし、もっと正しいやり方があるのかもしれませんがー

## 動作する一通りのコード

pywebview自体はpipでインストールしておくこと。

```python:webview_test.py
import webview

"""
Windowとやり取りするためのApiクラス
"""
class Api:
    def __init__(self):
        self.window = None

    # windowに対してevaluateしてjsを実行できる。
    def hello(self):
        self.window.evaluate_js(
            """
            console.log("hello debug!");
            """
            )
"""
この部分はウィンドウの動作とは別に動作する
"""
def threadFunction(window):
    print(window)

"""
Windowの生成等
"""
def main():
    with open("html/index.html", "r", encoding="utf-8") as fr:
        html = fr.read()

    api = Api()
    #apiクラスにwindowを渡しておくことで後から利用しやすくする
    api.window = webview.create_window(title = "Test App",
                                       html = html,
                                       js_api = api,
                                       width = 600,
                                       height = 400)

    webview.start(threadFunction, api.window, debug=True)

if __name__ == "__main__":
    main()
```

```html:html/index.html
<!DOCTYPE html>
<html>
	<head>
		<title>Test</title>
	</head>

	<body>
		<h1>WebViewTest</h1>
		<p>this is webview window</p>
		<button id="exec">Button!</button>
	</body>

	<script>
		<!--ドキュメントが準備出来次第いろいろする-->
		window.addEventListener("pywebviewready", function() {
			<!--buttonにイベントを追加、python側のAPIを呼び出す-->
			document.getElementById("exec").addEventListener("click", function(){
				pywebview.api.hello();
			})
		})
	</script>
</html>
```
## とりあえずの〆
webviewをpythonから利用できるということで便利なはずなのですが、いまいち使われていない様な気もします。

今回はやっていませんが、python側からDOMを操作するようにすればリアルタイムにコンテンツを変更してゆくようなものも作れますし、そういった便利な機能をまとめておけば便利に使えると思います。

画面遷移やダイアログ関係あたりが気になっているのでその辺りを次回探ってゆこうと思います。
【Docker】React+nginxを作る

[前回](https://qiita.com/huntas0624/items/53810397032b9df93356)、React+Nginxの環境を作ったはいいもののbuildにすごく時間がかかり、なかなかうまくいかなかったので再度挑戦してみた

手順↓
1\. いつも通り、Reactプロジェクトを作成
今回は***react-app***として作成します(typescriptで作ります)
`yarn create react-app react-app --template typescript`

2\. 作成した、ReactプロジェクトにDockerfileを作成
（react-appのフォルダの中にDockerfileを作成）
```dockerfile:Dockerfile
FROM node:lts-alpine

WORKDIR /app
COPY package.json .

RUN npm install
# build時間が短くなる
COPY . .
CMD ["npm", "start"]
```

3\. buildする
`docker build -t react-app .`でビルド
※.を忘れないように！！！

4\. docker runで動かす
`docker run --rm -p 8080:3000 react-app`
8080番で動かします

ポートの意味はこちらから
→[Docker runでportオプション（-p 8080:8080）や-dオプションする意味〜初心者向けにコマンドの解説〜](https://qiita.com/hirokihello/items/69df88ba55125c2aed39)

`http://localhost:8080/`に接続してみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/576a2660-7c6c-9a90-03b4-c94ce19d2482.png)

コードを変えたので`Hello React!!!`と表示されました！！

5\. nginxの環境を作成する
`Dockerfile`と同じ場所に`Dockerfile_Production`を作成する
```dockerfile:Dockerfile_Production
FROM node:lts-alpine as builder

WORKDIR /app
COPY package.json .

RUN npm install
# build時間が短くなる
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
```

6\. buildする
`docker build -t react-app:nginx -f Dockerfile_Production .`でビルド
※.を忘れないように！！！

`:nginx`でタグ付け、Dockerfileの指定で作成した`Dockerfile_Production`を選択します。

7\. docker runで動かす
`docker run --rm -p 8081:80 react-app:nginx`
最後の`react-app:nginx`で作ったものを指定します
ポートは先ほどと同じものを使えないので`8081`とします

`http://localhost:8081/`に接続してみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/ad3a15c8-7cc1-9fcf-e5c8-63309c2dee8c.png)
表示されました。`Hello React nginx!!!`にコードを変更したのでそれが表示されています。

以上、DockerでReact+nginxを動かす方法でした
ファイルはめるの、それawkでできますよ。

## 目的
ファイルの特定の文字列を探して、別のファイル内容を入れたいことありますよね。それ、awkで行ったっていう話です。
テキストファイル`foo.txt`の中に、`%hoge%`という文字列のみの行があるとして、そこを別のテキストファイル`hoge.txt`の中身で置き換えます。

## 結論

```{bash}
# filehameなら
cat       foo.txt         |
filehame -l%hoge% - hoge.txt  

# awkなら
cat       foo.txt         |   
awk '{  
  if( match($0, "%hoge%") > 0 ){ 
    while(( getline str < "hoge.txt" ) > 0 ){
      print str 
    } 
    close ("hoge.txt")
  }else{ print }
}'
```

## 説明
オープンソフト`filehame`は使い勝手がいいので好きなのですが、無償版は恐ろしく遅いので、これをawkの`getline`に置き換えただけです。

`filehame`を多段パイプになるとさらに遅くなります。10段で１秒ぐらいかかっていたのが、awkで`match()`を複数持たせることで10倍ぐらい早くなったとさ。

念の為、複数置換の例です。

```{bash}
# filehameなら
cat       foo.txt               |
filehame -l%hoge1% - hoge1.txt  |
filehame -l%hoge2% - hoge2.txt

# awkなら
cat       foo.txt               |   
awk '{  
  if( match($0, "%hoge1%") > 0 ){ 
    while(( getline str < "hoge1.txt" ) > 0 ){
      print str 
    } 
    close ("hoge1.txt")
  }else if( match($0, "%hoge2%") > 0 ){ 
    while(( getline str < "hoge2.txt" ) > 0 ){
      print str 
    }
    close ("hoge2.txt")
  }else{ print }
}'

```

## 参考
[filehame](https://uec.usp-lab.com/TUKUBAI_MAN/CGI/TUKUBAI_MAN.CGI?POMPA=MAN1_filehame)
m4というフィルタもあるようですが、よく知らないです。
R on vscode with jupyter notebook (failed) on mac



# Rとvscodeでハマりました

Rをvscodeでjupyternote book形式で動かそうとしてハマりました．

1.  condaは不要
2.  直接R上でvscode連携

が正解のようです．


# 十分にハマった手順


## やったこと

Rが入っている状態で，jupyter notebookからアクセスできるように．．．

    conda install -c r r-irkernel

from [How to Add R to Jupyter Notebook (full steps) 2022/2/25](https://datatofish.com/r-jupyter-notebook/)


## Rが動かない

```bash
> r
dyld[31520]: Library not loaded: @rpath/libreadline.6.2.dylib
  Referenced from: <185433D7-8B40-31AA-8BD9-465D23C57257> /Users/bob/opt/anaconda3/lib/R/lib/libR.dylib
  Reason: tried: '/Users/bob/opt/anaconda3/lib/R/lib/../../libreadline.6.2.dylib' (no such file), '/Users/bob/opt/anaconda3/lib/R/bin/exec/../../../libreadline.6.2.dylib' (no such file), '/Users/bob/opt/anaconda3/lib/R/bin/exec/../../../libreadline.6.2.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS@rpath/libreadline.6.2.dylib' (no such file), '/Users/bob/opt/anaconda3/lib/R/lib/../../libreadline.6.2.dylib' (no such file), '/Users/bob/opt/anaconda3/lib/R/bin/exec/../../../libreadline.6.2.dylib' (no such file), '/Users/bob/opt/anaconda3/lib/R/bin/exec/../../../libreadline.6.2.dylib' (no such file), '/Users/bob/opt/anaconda3/lib/R/lib/libreadline.6.2.dylib' (no such file), '/Users/bob/opt/anaconda3/lib/libreadline.6.2.dylib' (no such file), '/Users/bob/opt/anaconda3/libreadline.6.2.dylib' (no such file)
fish: Job 1, 'r' terminated by signal SIGABRT (Abort)
```


## 解決（未達）

dylibの番号が一致してないんだろうから．．．

```bash
  18   │ ls /Users/bob/opt/anaconda3/lib/R/lib/../../libreadline*
  19   │ ls -lat /Users/bob/opt/anaconda3/lib/R/lib/../../libreadline*
  26   │ cd /Users/bob/opt/anaconda3/lib/R/lib/../../
  20   │ ln -s libreadline.6.2.dylib libreadline.8.0.dylib
  21   │ ln -s libreadline.8.0.dylib libreadline.6.2.dylib
  24   │ ls -lat libicuu*
  25   │ ln -s libicuuc.58.2.dylib libicuuc.54.dylib
  27   │ ls -lat libicui18n*
  28   │ ln -s libicui18n.58.2.dylib libicui18n.54.dylib
```

これでRは起動可能．


# VSCodeから動かない

さらに，[Setting Up R with Jupyter](https://www.practicaldatascience.org/html/jupyter_r_notebooks.html) を試みるがerror.

```bash
> cd /Users/bob/opt/anaconda3/lib/R/modules/../../
> ln -s libssl.1.1.dylib libssl.1.0.0.dylib
> ln -s libcrypto.1.1.dylib libcrypto.1.0.0.dylib
```

を施して，再度トライするが，ダメみたい．


# えっと，成功法

rが動けばいいんで，Users/bob/opt/anaconda3/lib/R/ あたりを全部なくすか．

    conda remove "r-*"

で見事に消えた．その後，Rのプロンプトで，

    install.packages("IRkernel")
    IRkernel::installspec()

で動いた．jupyter notebookだが，anacondaは不要ということですね．


# 途中で．VSCodeエラー

途中でkernel accessの意味不明エラーが出てた．activity monitorで，cpuでcodeを検索して，xボタンで殺した．



------
 - **source** ~/Desktop/lecture_23/model_phys/r_on_code_with_jupyter.org
プラ子ちゃん召喚プロジェクト始動

# はじめに

エニプラボではエニプラのキャラクター プラ子ちゃんをGateboxというツールで召喚するアプリの作成を行っています。
今期は第一ステップとして、とりあえずアプリとして動く事をゴールとしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502127/b95d3888-c3f9-e69b-2ef6-adfa14507c62.png)

# モデリング

モデリングは長期インターンの大学生の方に作成して頂きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502127/64de8e2f-ee58-a9b2-860c-774d4913fe93.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502127/93f24a8b-2f88-e486-5f92-06de7acbfe4b.png)

# 音声認識

プラ子ちゃんは声をかけるとリアクションを返してくれます。
今期は特定のモーションと音声しか返しませんが、今後拡充していく予定です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502127/e3885660-ab40-dc1f-4dd5-081e478ccbed.png)

# 今後の取り組み

1. リアクションの拡充
プラ子ちゃんのモーションや返事のパターンを増やしていきます。 
1. プラ子ちゃんモデルのブラッシュアップ
モデルの着色や精度を向上せてます。
1. 音源の用意
今回はフリー音源の音声を再生しているだけですが、プラ子ちゃん専用の声を用意する予定です。
【Laravel】fillableを使ってシンプルなコードにしてみる

### fillableとは
Laravelを勉強していると度々出てくる`fillable`ですが、意味もよくわからずただなんとなくモデルに書いていました。

fillableとはホワイトリストと呼ばれるもので、DBに登録をする際にシンプルな処理ができるとのこと。

1つずつrequestで受け取ってという記述をシンプルなものにしてくれるそうです。

### 実際のコード
#### `$fillable`を使わない場合
```
    public function store(TrRecordRequest $request) {

        $validated = $request->safe()->only([
            'part',
            'menu',
            'set_type',
            'weight_first',
            'reps_first'
        ]);

        $trRecord = new TrRecord();
        $trRecord->user_id = Auth::id();
        $trRecord->part = $validated["part"];
        $trRecord->menu = $validated["menu"];
        $trRecord->set_type = $validated["set_type"];
        $trRecord->weight_first = $validated["weight_first"];
        $trRecord->reps_first = $validated["reps_first"];
        $trRecord->weight_second = $request->weight_second;
        $trRecord->reps_second = $request->reps_second;
        $trRecord->weight_third = $request->weight_third;
        $trRecord->reps_third = $request->reps_third;
        $trRecord->weight_fourth = $request->weight_fourth;
        $trRecord->reps_fourth = $request->reps_fourth;
        $trRecord->weight_fifth = $request->weight_fifth;
        $trRecord->reps_fifth = $request->reps_fifth;
        $trRecord->memo = $request->memo;
        $trRecord->tr_date = $request->tr_date;

        $trRecord->save();
        return redirect()->route('trrecords.index')->with(
            'message', '登録が完了しました'
        );
    }
```

登録するカラムデータが多ければ多いほど、
可読性が悪くなり、コントローラへ書く量が増えてしまいますね。

#### `$fillable`を使う場合
##### ①モデルに$fillableを記述する
```
class TrRecord extends Model
{
    use HasFactory;
    protected $fillable = ['tr_date','part','menu', 'set_type', 'weight_first', 'reps_first', 'weight_second', 'reps_second', 'weight_third', 'reps_third', 'weight_fourth', 'reps_fourth', 'weight_fifth', 'reps_fifth', 'memo'];
}
```
##### ②コントローラに記述をする
```
    public function store(TrRecordRequest $request) {

        $validated = $request->safe()->only([
            'part',
            'menu',
            'set_type',
            'weight_first',
            'reps_first'
        ]);

        $trRecord = new TrRecord();
        $trRecord->user_id = Auth::id();
        $trRecord->fill($request->all())->save();
        
        return redirect()->route('trrecords.index')->with(
            'message', '登録が完了しました'
        );
    }
```

かなりスッキリしました!

```
$trRecord->fill($request->all())->save();
```
この処理で`$fillable`に記述したカラムを一括でDBへ登録してくれます。
nfcpy-idノードが動かないときの対処方法

# きっかけ

以前、enebularブログで「社員証タッチで参加者リストを自動作成」という記事がありました。
MIFAREの社員証カードのタグをソニー製のNFCカードリーダーであるRC-S280で読み取ってGoogleシートに連携するという内容です。

https://blog.enebular.com/samples/iccard2spreadsheet/

この記事の公開は、2020年でして、今になって試してみたところ、動作しないことが発覚しました:disappointed_relieved:

# 問題・・・

原因は、こちらのノードにあるらしいということまではわかっています。

https://flows.nodered.org/node/node-red-contrib-nfcpy-id

が、私には、コーディングのスキルがありません。

でも、なんとかカードは読み取って欲しい・・・

そこで、ノードがうまく行かないときの対処方法を見つけましたので、ご報告します。

# 対処方法

## カードリーダーを使えるようにする

ここまではnfcpy-idノードを使う場合と一緒です。nfcpyをインストールしてICカードリーダーを使えるように設定します。ここでは、PaSoRi RC-S380を例にしています。

```
$ pip3 install nfcpy
$ cat << EOF | sudo tee /etc/udev/rules.d/nfcdev.rules
SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="06c3", GROUP="plugdev"
EOF
$ reboot
```

## カードリーダーが動作するか試す

カードリーダーにNFCのカードをかざしてみてから、

```sudo python3 /home/pi/nfcpy/examples/tagtool.py show```

として、プログラムを実行してみましょう。

TagIDが表示されれば問題無いです。

例えば、私の場合はMIFAREの社員証だったので、以下の様に表示されました。
```
pi@raspberrypi:~ $ sudo python3 nfcpy/examples/tagtool.py show
[nfc.clf] searching for reader on path usb
[nfc.clf] using Sony RC-S330 RCS956v1.30 at usb:001:004
** waiting for a tag **
Type2Tag ID=XXXXXXXX
```

もしTagIDが表示されなければ、nfcpyのソフトウェアが正常に動作していないですので、そこから原因を探すことになります。

## フローをつくる

execノード使ってこんなフローを組みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266424/4d5819a3-e211-1889-1051-7f1a0553ab9e.png)

プロパティはこんな感じです。

### excecノード

コマンド　`sudo python3 /home/pi/nfcpy/examples/tagtool.py show`
出力 `spawnモード`
名前 `nfc`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266424/7d491772-34ae-03bc-be1a-06f2f23d244e.png)

### changeノード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266424/147cd35e-634d-5199-23c7-963bcbc29196.png)


このフローを実行すると、カードリーダーでカードをかざすとpayloadにtagtool.pyの読み取り結果が格納されます。
debugタブに、例えば、`Type2Tag ID=XXXXXXXX`などと表示されます。
changeノードで一旦読み取り結果がクリアされて、カードリーダーの読み取り待ちになります。

# まとめ

ノードが動かないとき、ノードを修正するスキルがあればいいのですが、できないため、execノードでなんとかカードを読み取るという目的は達成できました。

今日使用したフローは、enebularのdiscoverで公開しています。

[使用したフロー](https://enebular.com/discover/flow/144a5310-a4ff-4038-b3bf-e12c6ca22330)

このシンプルなフローでは、カードのタグを2回読み取ってしまったりするので、フローの後段で工夫が必要にはなると思います。今後、機会があれば、対応方法を紹介したいと思います。


# 参考

https://blog.enebular.com/nodes/letsuse-google-spreadsheet-node/

https://qiita.com/jksoft/items/00cb286d7cdd1ac3ef45
intのmax値を超えるとどうなる

```java
    public static void main(String[] args) {
        int i1 = Integer.MAX_VALUE;
        System.out.println(i1);
        System.out.println(i1+1);
        System.out.println(i1+2);
        System.out.println("----------------------");
        byte b1 = Byte.MAX_VALUE;
        System.out.println(b1);
        System.out.println(b1+1);
        System.out.println(b1+2);
        System.out.println(b1+2147483647-Byte.MAX_VALUE);
        System.out.println(b1+2147483647-Byte.MAX_VALUE+1);
    }
```
max値を超えるとmin値になる
byteは計算すると、intのmax値となる
```
2147483647
-2147483648
-2147483647
----------------------
127
128
129
2147483647
-2147483648
```
module 化した Terraform に AWS リソースを import する

# 先に結論

`terraform import module.[module name].aws_hogehoge [target]` のようにすればいい。


# 背景

AWS リソースを Terraform でいい感じに構築して構成管理していたが、あまり扱わないリソースをいきなり Terraform で作ろうと思うと Try&Error が多くなったりしてめんどくさい。
最初はやっぱ AWS 管理コンソールからポチポチしてしまって、必要な情報がどういうものになるのか把握したうえで `terraform import` → コピペでリソースを増やすほうが効率的。
というわけでやってみた。


# 失敗例

SNS topic 作ったことなかったし、管理コンソールから作成→ terraform import してみたが失敗。

まずは terraform file を作って

```terraform:sns.tf
resource "aws_sns_topic" "alert_mail" {

}
```

import

```zsh
% terraform import aws_sns_topic.alert_mail arn:aws:sns:ap-northeast-1:[account_id]:[sns-name]
Error: resource address "aws_sns_topic.alert_mail" does not exist in the configuration.

Before importing this resource, please create its configuration in the root module. For example:

resource "aws_sns_topic" "alert_mail" {
  # (resource arguments)
}
```

失敗した。なぜだろう。


# 失敗の原因と解決

この Terraform は、staging 環境と production 環境向けに同じ resource file を共有し、それぞれ変数で作り分ける手法を取っていた。

```zsh:こんな感じ
% tree .
.
├── production　←production 環境向けの設定
│   ├── main.tf
│   ├── terraform.tfvars
│   └── terraform.tfvars.sample
├── source　←terraform 本体（
│   ├── （諸々省略）
│   ├── variables.tf
│   └── hoge.tf
└── staging　←staging 環境向けの設定
    ├── main.tf
    ├── terraform.tfvars
    └── terraform.tfvars.sample
```


production / staging それぞれの main に↓のように設定して module として Terraform 本体を読み込むようにしていた。

```terraform:main.tf
module "staging" {
  source = "../source"

  hogevar = var.hogevar
}
```

このように module 化されている場合、terraform import はどこに import すべきなのか見失うらしい。
なので、module を指定してあげれば import できた。

```zsh
% terraform import module.staging.aws_sns_topic.alert_mail arn:aws:sns:ap-northeast-1:[account_id]:[sns-name]
（略）
module.staging.aws_sns_topic.alert_mail: Import prepared!
  Prepared aws_sns_topic for import
（略）
Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
```

あとはここから terraform show すればどんなパラメータが設定されてるのかわかるので、必要な情報を .tf ファイルに転記するだけで簡単に Terraform で構成管理することができる。


# 終わりに

今回は Terraform (AWS) ネタでしたが、ねこじゃらしは AS 番号を取得し、ピアリング活動も積極的に行っています。（AS 146981）
オンプレからクラウドインフラにとどまらず AS 運用まで多くのことに携わりたいエンジニアを積極的に募集しています。
https://www.green-japan.com/company/2706/job/138717
TypescriptのstrictNonNullとstrictClassInitializersがなぜ大切か

はいさい！オースティンやいびーん！

# 概要

TypescriptのstrictNonNullとstrictClassInitializersについて解説します。

# `strictNonNull`とは

TypeScriptは、本来、undefinedと null を完全に違う型として認識しています。
実際、JavaScriptでも `undefined !== null` ですし、undefinedと null を大体同じだと勘違いして使っていると、痛い目に遭います（筆者はずっと誤解していました:sweat_smile:）。

しかし、TypeScriptの緩い設定だと、これらの違いについて文句を言わないようになっています。

`strictNonNull`を有効にすると、Runtimeで絶対にエラーになるようなコードに気づくことができます。

そして、undefinedの可能性がある戻り値について、厳しく指摘も入るようになります。

以下のコードをみてみましょう。

```typescript
const myLetters = ['a', 'b'];
const isOneLetter = myLetters.find(v => v === 'c').length === 1
```

myLettersのfindの戻り値を考えましょう。何の型になるでしょうか？
'c'が配列にないので、stringではなく、undefined になりますね。
undefinedには length はないので、JavaScriptだったらここでまず転けますね。

strictNonNullが有効だと、ここでTypeScriptはそれを教えてくれるのです。

そして以下のように対応します。

```typescript
const myLetters = ['a', 'b'];
const isOneLetter = myLetters.find(v => v === 'c')?.length === 1 // findの戻り値がundefinedだったら、.lengthをGetせずに、undefinedをそこで返す
// OR
const isOneLetter = myLetters.find(v => v === 'c')!.length === 1 // エラーはそれでも起こる、危ない！
```

`!`もしくは `?` を使って、TSに`undefined`の可能性があるコードに対してどうするべきかを教える必要があります。これらの機能は`NonNullAssertions`と言います。

# strictPropertyInitializationとは

上記のstrictNonNullとセットで来るのは、strictPropertyInitializationの設定です。

以下のコードを見てみましょう。

```typescript
class MyComponent extends OnInit {
 items: Item[];

 ngOnInit() {
  this.items.forEach(item => item.viewed = true);
 }
}
```

this.itemsの Propertyはどこでも設定されていないので、ngOnInitでエラーになります。なぜなら、this.itemsは Item[] ではなく、 undefinedだからです。

なので、ここでは二つ、対策を施します。

## 初期値を与える場合

```typescript
class MyComponent extends OnInit {
 items: Item[] = [];

 ngOnInit() {
  this.items.forEach(item => item.viewed = true);
 }
}
```

## 絶対に定義されることをわかっている場合

```typescript
class MyComponent extends OnInit {
 @Input() items!: Item[];

 ngOnInit() {
  this.items.forEach(item => item.viewed = true);
 }
}
```

##定義されない可能性がある場合

```typescript
class MyComponent extends OnInit {
 @Input() items?: Item[]; // TS上、Item[] | undefinedになるのです。

 ngOnInit() {
  this.items?.forEach(item => item.viewed = true);
 }
}
```

上記の対策を施すと、いろんな場面で起きるエラーを未然に防ぐことができます。

# まとめ

以上、strictNullChecksとstrictPropertyInitializerについての解説ですが、さらに知りたい方は、TypeScriptの正式ドキュメントをご覧ください！

https://www.typescriptlang.org/tsconfig#strictNullChecks

また、勉強会を開いてもいいのですが、もし勉強会が役に立ちそうなら、オースティンまでご連絡ください。
【VSCode】OpenAPIの3.0系を指定したいのに3.1系を強制された

# 概要
VSCodeでOpenAPIのyamlファイルを編集していたところ、以下のエラーが発生しました。
```
String does not match the pattern of "^3\.1\.\d+(-.+)?$".yaml-schema: openapi.json
```
該当のファイルは以下になります。この「3.0.3」の部分でエラーが発生してしまいます。

```yaml
openapi: 3.0.3
info:
  title: API
  description: API
  version: 1.3.0
  contact:
    email: example@gmail.com
```
以下の画像の通り
![スクリーンショット 2022-12-21 13.43.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637441/ab6c8f0a-a238-4f56-70f1-4f8b65762d34.png)

OpenAPIのバージョンとしては3.0系を使用したいのですが、なぜか3.1系でなければならないと怒られています。
このエラーを解消しました。

# 原因はVSCodeの拡張機能「YAML」のせいっぽい
Linterとして[Spectral](https://marketplace.visualstudio.com/items?itemName=stoplight.spectral)を使用しているのですが、この拡張に依存する[YAML](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)という拡張機能が主な原因のようでした。

> I did a little bit more digging, and it looks like it's somehow caused by RedHat's YAML extension which we depend on for yaml support. It seems to be picking it from schema store at https://www.schemastore.org/api/json/catalog.json which has OAS 3.1 schema. It can be disabled by turning "YAML > Schema Store > Enable" setting to off.

同じようにYAMLに依存している拡張機能[OpenAPI (Swagger) Editor](https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi)のissueで挙げられていたように、YAMLがOpenAPI 3.1系の定義を自動で参照するらしく、これにより3.0系を使用したくても3.1系の定義でLinterが起動してしまうようです。

# 解消方法
VSCodeの設定で以下を検索し、YAMLの設定を変更します。
```
@ext:redhat.vscode-yaml store
```
YAML > Schema Store > Enable　のチェックを外せばエラーは解消されました。

# 参考
https://github.com/42Crunch/vscode-openapi/issues/130

https://github.com/redhat-developer/vscode-yaml/issues/532
axios-retryでリトライ機能を追加

## 経緯
axios使用したAPIでリトライ機能を実装することになり調べた結果
Nuxt.jsにデフォルトで入ってたaxios-retryが使いやすいと思われたため使用した。
## サンプルソース

```
import axiosRetry from 'axios-retry';

axios.get('http://sample.jp/')

axiosRetry(axios, { 
    // ここでリトライ回数を設定
    retries: 10,
    retryCondition: () => true,
    retryDelay: (retryCount) => {
      return retryCount * 1000
    }
});
```

## 補足
retryConditionをtrueにするとHTTPステータス4XX,5XXでリトライする。
retryConditionをfalseにすると5XXのみでリトライするがPOSTのみfalseにしても4XXでリトライする。

下記GitHub参考
https://github.com/softonic/axios-retry

※はまりポイントだったので補足で説明した。

## おわりに
axiosRetryの項目を数行書くだけでリトライ機能が実装出来るのでお手軽でした。
useStateの基本の書き方

<h1>概要</h1>
今回はReact hooks の種類の一つである <b>useState</b> の基本的な使い方についてまとめた記事になります。
<br>useStateが使われるシーンとして、Reactでアプリケーションを開発する際に、動きをつけたい場合に使われる事が多いです。

例えばカウントアップ アプリだと数値を変動させたいときに使用されます。
（todoアプリの作成の際にタスクを追加・削除することがある。この際にuseStateが用いらます）

<h1>hooksを使う上での注意点</h1>

1 条件分岐 等で呼び出さないこと
　　→hooksは最初に呼び出す必要がある。

2 クラスコンポーネントではhooksは使えない
　　→関数コンポーネントで使用しましょう。


<h1>useStateの書き方</h1>
カウントアップ（ボタンを押すと+1ずつカウントされていく処理）を例にuseStateの解説を1行ずつしていきます。

下記のコードは完成形のコードになります。

```jsx
import React, { useState } from "react";

const Counter: React.FC = () => { 
  const [count, setConst] = useState(0);
  return <button onClick={() => setConst(count + 1)}>{count}</button>;
};

export default Counter;
```

<b>1行目↓</b>
useStateを使用する際は、useStateのimportを下記の様に行う必要があります。
```jsx
import React, { useState } from "react";
```
<b>2行目↓</b>
「const 関数名: React.FC = () => { 」
const の後にくる文字列を任意で決め、関数として使用します。（下記のコードでいうCounter）
```jsx
const Counter: React.FC = () => { 
```
<b>3行目↓</b>
・「count」は変数で任意の文字列で定義することができます。
・「setCount」は任意で定義したcountにsetをつけた関数になります。
　（setCountはcountを更新して行くための関数）
・「useState(0);」では初期値を設定します。
　　（今回の場合だとカウントアップする前に画面に表示される数値は「0」なので0と書いています）
```jsx
const [count, setConst] = useState(0);
```
<b>4行目↓</b>
・「return」の中で書いたコードがブラウザに反映さらます。
　　（htmlでいるbodyタグと同じ役割）
・「onClick={() => ()}」をbuttonタグの中に書くことで、そのボタンを押した時に処理が発火します。
・「setConst(count + 1)」の処理の内容として、count変数に+1ずつしていき、それをsetCountの値として更新していっています。
・「{count}」ではブラウザにカウントアップしていく数値を表示しています。

```jsx
 return <button onClick={() => setConst(count + 1)}>{count}</button>;
```
<b>5行目↓</b>
・「export default Counter;」はコード最終行に
　「export default 2行目で宣言した関数名;」をつける必要があります。
```jsx
export default Counter;
```

<h1>まとめ</h1>
今回はReact hooks の種類の一つである <b>useState</b> について学びました。

hooksの中では１番使われる事が多いです。
今後のアプリ作成で動きを作る際に参考にしていただけると幸いです。
すべてのパターンを返す関数

typescriptで、与えられたパターンをすべて返す関数を作ってみました。

網羅的にチェックをする場合に使えるかもしれません。

```ts
// by KatagiriSo
const patterns = <A>(list: A[][]) =>
list.reduce(
  (as: A[][], pat: A[]) =>
    as.flatMap((a: A[]) => pat.map(b => a.concat([b]))),
  [[]]
)
```

これを使うと
```ts
console.log(patterns([["1", "2"], ["a", "b", "c"],["A","B"]]))
/*
[
  [ '1', 'a', 'A' ],
  [ '1', 'a', 'B' ],
  [ '1', 'b', 'A' ],
  [ '1', 'b', 'B' ],
  [ '1', 'c', 'A' ],
  [ '1', 'c', 'B' ],
  [ '2', 'a', 'A' ],
  [ '2', 'a', 'B' ],
  [ '2', 'b', 'A' ],
  [ '2', 'b', 'B' ],
  [ '2', 'c', 'A' ],
  [ '2', 'c', 'B' ]
]
*/
```

のようにすべてのパターンが網羅された配列を返します。
AZ-900に合格した話

本エントリーはAdvent Calendar 2022「[NKC-UG Advent Calendar 2022](https://qiita.com/advent-calendar/2022/nkc-ug)」の2日目のエントリーです！

# はじめに

こんにちは。[ノル](https://twitter.com/noll6451)です

今回は「NKC-UG」主催のアドベントカレンダー「[NKC-UG Advent Calendar 2022](https://qiita.com/advent-calendar/2022/nkc-ug)」の2日目にエントリーしました
## きっかけ
Microsoftの資格を一通りとったので、備忘録代わりです。(いま調べたらMS900受験できるようになっているので、近いうちに取りに行く)
自分の合格したMicrosoftの資格一覧は[こちら](https://www.linkedin.com/in/rei-suzuki-22b443211/)で見れます。
~~NKC-UGの代表だから仕方なくではない~~

#この記事の対象者

- Microsoftの認定試験を受験予定の人
- Azureを勉強したい初心者の方
- AZ900を受験する方向け
- 学生向け

## この資格の説明
[公式](https://learn.microsoft.com/ja-jp/certifications/azure-fundamentals/)では
>サービスとしてのインフラストラクチャ (IaaS)、サービスとしてのプラットフォーム (PaaS)、サービスとしてのソフトウェア (SaaS) に加えて、パブリック、プライベート、ハイブリッド クラウドなどのクラウド コンピューティングの概念、モデル、およびサービスに関する知識を証明する。
Azure がセキュリティ、プライバシー、コンプライアンス、および信頼関係をどのようにサポートしているかについての専門知識を示す。

となっております。

難しく書いてありますが、Azureを使う上での基礎知識が問われる試験です。
ちなみに
この試験は、社会人、学生関係なく**無料**のバウチャーがもらえる方法があります。
(後で説明します)

## 試験予約編
~~社会人も学生も無料になる方法があります(社会人の方はこちらの方法ですが、学生の方は2通りあります)~~
まずは、下から有無言わさず予約してください。この時のメールアドレスはしっかりと保管してください(個人のメールアドレスが推奨です。)

https://www.microsoft.com/ja-jp/events/top/training-days/azure?activetab=a1:primaryr4

~~前から録画してある動画を流すウェビナーなので、ぶっちゃけどんな状況でも受けれます。ただしっかりと出席だけはしてください。(バウチャーがもらえないので)~~


:::note alert
残念ながら改悪されてしまい、バウチャーがもらえなくなりました。
社会人だと50%で受ける方法はあります。学生は無料です
:::


## 勉強方法
上記のウェビナーは、特に初心者にはお勧めです。疑問に思ったところも聞けます！


https://learn.microsoft.com/ja-jp/certifications/exams/az-900

まずは**ヒント**というところをしっかりとみてください(重要です)
実際の試験の操作も体験できます。
その次に下にスクロールすると、勉強できるようにラーニングパスがあるので
それに沿って勉強すれば十分です。(もちろん無料です)

ただ問題集もやったほうが合格率高まります。(TAC,Udemyがいいと聞いたことがあります.自分は使ったことないので、分かりません)
一応公式が出しているサンプル問題もあります
https://learn.microsoft.com/ja-jp/certifications/resources/az-900-sample-questions?azure-portal=true

# 試験を受けるときの注意点

- 日本語がおかしい場合がある(英語に直す、察する)
- 採点されない問題が出てくる
- 出題範囲にない問題が出てくる(たぶん採点されてない？)
- 人によって問題数が違う
- 意外と時間がないので、サクサク進める(後から回答し直せる)
- 分からなくてもとりあえず何かしら選ぶ(1000点中合格スコア700だけど、7割ではないらしい)


これからMicrosoft試験基礎シリーズが続きます。
ぜひこれを機にとってみてはいかがですか？？(実は、基礎資格は有効期限はないです)
ちなみ学生ですが、実は単位認定される可能性があります。

https://learn.microsoft.com/ja-jp/certifications/college-credit


皆さんの合格をお祈りしてます。
【Alpine.js】Livewireのプロパティと連携させるなら@entangle使いまヒョ

# ＠entangleとは
LivewireとAlpine.jsのプロパティを共有することができます。

# 何ができるのか
Alpine.js、Livewireのプロパティの値を変更させると、もう一方のプロパティの値も変更されます。
プログラミング言語で言い表せば、PHPとJavaScriptを相互に連携させることができるというワケ。

# コード例（公式ドキュメントより）

```php
// Livewireのコンポーネント

class Dropdown extends Component
{
    public $showDropdown = false;

    public function archive()
    {
        ...
        $this->showDropdown = false;
    }

    public function delete()
    {
        ...
        $this->showDropdown = false;
    }
}
```
```html
@entangleでLivewireのshowDropdownプロパティをopenプロパティに代入している
                        ↓
<div x-data="{ open: @entangle('showDropdown') }">
    <button @click="open = true">Show More...</button>

    <ul x-show="open" @click.away="open = false">
        <li><button wire:click="archive">Archive</button></li>
        <li><button wire:click="delete">Delete</button></li>
    </ul>
</div>
```
この時、Archiveボタンをクリックすれば、Alpine.jsのopenプロパティの中身も連動して値がtrueになります。

# ここ大事かもポイント
### Alpine.js側からプロパティを変化させるたびにLivewireからリクエストが送信される

Alpine.jsはフロントの画面操作に使うことが多いと思います。
ゆえに、プロパティの変化もLivewireのプロパティと比べて比較的多くなります。
Alpine.jsとLivewireと連携しているということは

<b>Alpine.jsのプロパティ更新の回数
＝　Livewireのプロパティ更新の回数
＝　Livewireのリクエスト送信回数</b>

になるはずです。おそらく。
<b><font color="red">Livewireのリクエスト回数が多くなれば当然、動作がウンコになりますのでこれを防ぐ方法だけ紹介しておきます。</font></b>

::: note
<b>解決方法</b>
Livewire使用者おなじみ、.defer

```
<div x-data="{ open: @entangle('showDropdown').defer }">
```
これでAlpine.jsの変更ごとにLivewireを更新されることはなくなります。
:::

# まとめ
これこそLivewireとAlpine.jsを共に使うメリットやと思います。
バチコリと活用してって開発効率ブチアゲていきましょう。

Livewireと共にあらんことを:thumbsup_tone2:
そうだ、100万件データ作ろう

# はじめに
私は文系卒プログラミング未経験で開発部署に配属された、社会人2年目の新米エンジニアです。
「まだまだ高度な技術的な記事なんて書けない、、、だけどポエム的な記事も新卒1年目の子がいい記事を書いてくれているので2年目の自分が何か書けることなんてあるかなあ」と避けていました。

ですが、自分が会社内の活動でQiita部なるものに入っていること、弊社の去年のアドベントカレンダーの以下の記事などに背中を押されて今回本記事を書くことにしてみました。
[その技術記事、価値あります](https://qiita.com/kabik/items/53655f8fc81c7844f055)

# 100万件データ作ろう
自分が担当していたお客様からの問い合わせを調査するために、100万件ほどマスタデータを作成する必要がありました。
初めは「ただデータを100万件作ればいいだけね」と軽く考えていたのですが、意外と沼にはまってしまったのでその方法をTips的に書き残してみます。

## 挫折した方法たち
#### 方法その1 画面からマスタを100万件登録する
お客様から問い合わせいただいたデータを自社製品の画面から直接登録するという一番シンプルな方法です。
不可能ではないですが、100万件を手入力で登録するのはあまりにも現実できてないので却下。

#### 方法その2 100万件分のデータのdatファイルを作成し、ツールでデータベースに取り込む
まずdatファイルの作成自体が大変でしたが、コピー＆ペーストを繰り返しながら力技で一旦10万件分のデータのdatファイルを作成しました。
このファイルを適宜中身を書き換えてデータベースに取り込む作業を10回繰り返せば100万件だ！！と思っていました。
しかし、データベースにdatファイルを取り込むツールの特性上1件1件insert文を実行しているため合計10万回もSQLを実行することになり、ツールが固まってしまいました。
この方法も挫折。

#### 方法その3 製品のCSV取込機能を使う
既に方法その2でdatファイルは作成済みであり、自社製品の機能でCSVファイルをバッチ処理で取り込み、登録する機能が存在しているためそれを利用しました。
しかし、10万件一気に取り込むと1回のバッチ処理にかなり時間がかかるためこちらの方法も挫折。

## ROWNUMを使ってみた方法
#### [ROWNUM](https://docs.oracle.com/cd/E16338_01/server.112/b56299/pseudocolumns009.htm)について
ROWNUMを使うことで実行したSQLの取得結果に対して連番を振ることができます。
例えば以下のようなmembersテーブルがあったとします。
| name | age | id |
|:-----------:|:------------:|:------------:|
| 田中太郎 | 22 | 1 |
| 山田花子 | 24 | 2 |
| 佐藤二郎 | 23 | 3 |
| 鈴木光一 | 20 | 4 |
| 小林優子 | 25 | 5 |

`SELECT ROWNUM, name, age, id FROM members`を実行すると、
| ROWNUM | name | age | id |
|:-----------:|:-----------:|:------------:|:------------:|
|1| 田中太郎 | 22 | 1 |
|2| 山田花子 | 24 | 2 |
| 3|佐藤二郎 | 23 | 3 |
| 4|鈴木光一 | 20 | 4 |
| 5|小林優子 | 25 | 5 |

このように連番が振られます。

以下のようにWHERE句に指定するとレコード数を制限して連番を取得することもできます。
`SELECT ROWNUM, name, age, id FROM members WHERE ROWNUM <= 3`
| ROWNUM | name | age | id |
|:-----------:|:-----------:|:------------:|:------------:|
|1| 田中太郎 | 22 | 1 |
|2| 山田花子 | 24 | 2 |
| 3|佐藤二郎 | 23 | 3 |

#### 実際にROWNUMを使って100万件データを作った方法
上記のmembersテーブルに100万件データを作ると仮定します
membersテーブルはidカラムをキーとしているため、idが異なればname、ageに関しては同じ値でも一意と見なされる、とします。
*  なるべくデータ件数が多い既存テーブルを探す
例えば以下のようなgoodsテーブルを既存テーブルを例とします。
goodsテーブルには100万件データが存在しています。

| id | product_name | price |
|:-----------:|:------------:|:------------:|
| 0000001 | りんご | 100 |
| 0000002 | バナナ |150 |
| 0000003 | みかん | 300 |
⋮
| 0999999 | いちご | 350 |
| 1000000 | メロン | 500 |

*  既存テーブルを利用して、100万件のレコードを作成したいテーブルにINSERTする
goodsテーブルから100万件を取得し、ROWNUMを使ってidを連番で割り振りINSERTします。
`INSERT INTO members (name, age, id) SELECT '田中太郎', 22, ROWNUM FROM goods WHERE ROWNUM <= 1000000`

| name | age | id |
|:-----------:|:------------:|:------------:|
| 田中太郎 | 22 | 1 |
| 田中太郎 | 22 |2 |
| 田中太郎 | 22 | 3 |
⋮
| 田中太郎 | 22 | 999999 |
| 田中太郎 | 22 | 1000000 |

これでmembersテーブルに100万件データを作ることができました。
    nameとageは同じ値になっていますが、idがキーであるためすべてのデータが一意となります。

イメージとしてはgoodsテーブルから100万件分のデータの箱だけもらい、
そこにmembersテーブルにINSERTするための必要な情報を詰めるイメージです。

1回のSQL実行で済むため、挫折したいくつかの方法に比べて時間もそこまでかかりませんでした。

# おわりに
今回は大量のデータを作るには、というとてもシンプルなテーマをSQLによって実現した方法を書いてみました。
内容自体はごく簡単ですが、若手にとっては意外とシンプルなことに思えても実現方法が思いつかないこともあるかと思います。
私自身のあるあるなのですが、思いつかないと「えいっ」と力技で乗り切ってしまうことが多々ありました。
しかし、重要なのは何かを実現するための方法を調べたり実践したりするという試行錯誤を重ねて、後に楽をするための努力を初めに惜しまないことだと思います。
本記事がそんな最初の努力の一助になれば幸いです。
ROS2のリポジトリにプルリクきたら自動でビルドテストする

Github Actionを使うと、プルリクやプッシュをトリガーにして自動テストや自動ビルドができます。今回は、ROS2のCIをGithub Actionで回す方法についてお話します。ROS2の公式CIは遅くて辛いので、良さそうなリポジトリを見つけましたので、ご紹介したいと思います。
## 方法
:::note info
以下の方法はBuildが通るかの確認のみです。テストなどは実行しません。
:::

ROS2のプロジェクトがあるリポジトリ 
-> Actions 
-> set up a workflow yourself 
-> main.ymlに以下をコピペ & コミット
```yml
name: Build
on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checking out
        uses: actions/checkout@v2.3.4
      - name: Building and testing
        uses: TakanoTaiga/ros2-ci@v1.0.1
```

勝手にビルドがはしる。

## 使用させていただいたリポジトリ
以下のリポジトリをフォークして自分が使いやすいように書き換えました。本家開発者様の皆さま爆速ROS2CIありがとうございます。テストも回したい場合や依存関係がある場合などは本家様のリポジトリを参照お願いいたします。

https://github.com/ichiro-its/ros2-ci
Red Hat OpenShift on IBM Cloud(ROKS)からIBM Log Analysis(旧LogDNA)に出力され、アーカイブされたIBM Cloud Object Storage(ICOS)上のログを IBM Cloud Data Engine(旧SQL Query)で解析するときのTips

:::note warn
IBM Cloud Data Engine(旧SQL Query)は2024年1月18日をもって非推奨となり、2024年2月18日以降、新規インスタンスの作成が出来なくなりました。さらに、2025年1月18日をもってEoSとなるため、現在ご利用のインスタンスから後継サービスであるAnalytics Engineなどの利用へ変更する必要があります。
:::

## はじめに

Red Hat OpenShift on IBM Cloud(ROKS)のログを、IBM Log Analysis(旧LogDNA)に出力していて、そのログをIBM Cloud Object Storage(ICOS)にアーカイブしているとします。

そのようなICOS上のログを、IBM Cloud Data Engine(旧SQL Query)で解析する例を以前書きました。

https://qiita.com/hirokuda/items/37a68b3479ae9e9d8ef3

## 状況

この検索対象にROKSのログが含まれているときに、このようなエラーが発生するようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307720/35a0f1fe-afc6-e7d4-c412-bd9f218d20fa.png)

このようなエラー文言で色々検索しても、欲しい情報になかなかヒットしないです。

```
SQL execution failed

Found duplicate column(s) in the data schema: name, namespace

If you open a support ticket, it will already contain a reference to this job. Select the appropriate account in the console.
```

## 原因

原因としては、例えば`namespace`と`Namespace`というように、大文字小文字の違いを除いた同じ名前のフィールドがログの中に含まれてしまっているためです。

具体的には以下のように、OpenShift(Kubernetes)のネームスペースによって、その名前が入っているフィールド名が全部小文字だったり、頭文字が大文字だったりしました。

```
"namespace": "ibm-observe"
```

```
"Namespace": "openshift-marketplace"
```

このようログが混在したものを`STORED AS JSON`で読み解こうとすると、先のエラーが発生してしまうようです。

## 解決策

こちらに記載されていました。

Query data with an unstable schema
https://cloud.ibm.com/docs/sql-query?topic=sql-query-overview#query-logs

`STORED AS JSON`としていたところを、`STORED AS TEXT`にして、必要なフィールドを`get_json_object`で持ってくるようにします。

例えば、このようにしたかったことを、

```
SELECT _source._line as line 
FROM cos://jp-tok/ICOSBUCKETNAME/year=2022/month=12/* STORED AS JSON 
WHERE _source._app = 'アプリ名' AND _source._line LIKE '%メッセージIDとか%'
```

このようにすれば、欲しい結果が得られるようになります。

```
WITH logs (
  SELECT get_json_object(value, "$._source._app") as app,
  get_json_object(value, "$._source._line") as line 
  FROM cos://jp-tok/ICOSBUCKETNAME/year=2022/month=10/day=31/* STORED AS TEXT
)
SELECT line
FROM logs
WHERE app = 'アプリ名' AND line LIKE '%メッセージIDとか%'
```

## おまけ

解決策にあるクエリーを見ると、LogDNAのログに含まれるUNIX時間のタイムスタンプ`_ts`をハンドリングしています。

これを参考にしつつ、せっかくなので日本時間で表示するには、以下のようにします。

```
WITH logs (
  SELECT get_json_object(value, "$._source._app") as app,
  get_json_object(value, "$._source._line") as line,
  from_unixtime(32400 + get_json_object(value, "$._source._ts") / 1000, 'yyyy-MM-dd HH:mm:ss') as timestamp  
  FROM cos://jp-tok/ICOSBUCKETNAME/year=2022/month=10/day=31/* STORED AS TEXT
)
SELECT timestamp, line
FROM logs
WHERE app = 'アプリ名' AND line LIKE '%メッセージIDとか%'
```

ただし、おそらくLogDNAが受け取ったタイミングの時刻なので、ログ本体に出力時点の時刻が出ている場合、厳密に見るならばそちらを使用するべきですね。

以上。

きっと忘れた頃に同じことで悩むと思うので、その時には検索にヒットするといいなと思いつつの書き込みでした。