OmniAICreator/Qiita-1.07M huggingface dataset:
APIとは・・・

お疲れ様です。
Salesforceエンジニア向けの記事を書いております。アドミンKと申します。

今回はAPIについてまとめたいと思います。
最近、Twitter社がTwitterAPIを有料化すると世間の話題に上がりましたが、APIはSalesforceを扱う上でも重要になってきますので、覚えておいて損はないでしょう。
それでは、さっそくAPIについてまとめていきます。

APIとは、
Application Programming Interface(アプリケーション プログラミング インターフェース)の頭文字をとったものです。
インターフェースは何かと何かをつなぐものという意味であり、
APIの場合は「アプリケーション(ソフトウェア)とプログラミングをつなぐもの」という意味になります。

例えば、パソコンのUSBに携帯機器をつないだ時、パソコンと携帯機器の間でデータの連携などができますよね。
この時のUSBの働きを、Web上で行っているのがAPIです。

Twitterでも、ユーザ同士のつながりや、やり取りの履歴、ユーザのプロフィールなどを、APIを通して外部のシステムからでも参照することが可能です。
これはデータ連携を行えるようにTwitter側がAPIという、データ参照用の窓口を設置し、それを外部に公開しているからです。
外部のソフトウェアはAPIを通して、Twitterなどのアプリケーション(ソフトウェア)のデータを取得してくるという仕組みです。

このように、APIはデータを提供する側が用意しているソフトウェア同士がデータ連携を行うための窓口のようなものだと、覚えておいてください。


以上が私のAPIの認識です。
細かく言えば、違う点もあるかもしれませんが、大まかな部分は間違っていないと思います。
冒頭にもお話したように、APIはSalesforceにも用意されており、データローダなどを使う際にも関係してきますから、そちらの内容に関しては後日、細かく記述しようと思います。

ここまで読んでいただきありがとうございます。
一緒に勉強頑張りましょう。
不思議なコード ～java ジェネリクス型の型消去～

# この記事の目的
簡単なコード例から、javaのジェネリクス型における型消去（Type Erasure）という仕組みを見ていきます。

ちょっと変なコードがある→面白そう　と感じてもらえればうれしいです。

この記事では、型消去は簡単な解説にとどめます。
詳しい説明は、他の記事や公式ドキュメントに譲ります。
　参考：java 公式ドキュメント(Type Erasure)
　https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
# まずはコード
~~~java: Container.java
public class Container<V>{
    V value;
    public void setValue(Object value){
        this.value=(V)value;
    }
}
~~~
~~~java:Main.java
public class Main{
    public static void main(String... arg){
        Container<String> con=new Container<>();
        Integer i=0;
        con.setValue(i);
    }
}
~~~

# おかしなコードですね
まず、`setValue(value)`の引数型が`Object`です。ここは、`V`を引数の型にしたほうがよいですが、コンパイルは通りそうです。

つぎに、`con.setValue(i)`の部分を見てください。`String`を`value`として持つ`con`に`Integer`型の変数`i`を入れようとしていてまずいですね。

では、コンパイルが通るか・実行できるかという観点ではどうなのでしょうか？

# このコードは実行できるのか？
次の二つの観点で見ると、このコードはどうでしょうか。
- コンパイルは通りますか？
- それとも実行時エラーが投げられる？(`ClassCastException`？)
# 答えは...
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
↓
# 実は正常に動きます
実は、全く問題なく動きます。
※コンパイル・実行はできますが、`this.value=(V)value;`の部分でwarningは出ます。

例えば、次のような`print()`を実装しても、ちゃんと動きます:
~~~java: Container.java
//Containerクラスの中
    public void print(){
        System.out.println("value is "+this.value);
    }
~~~
~~~:con.print()の実行結果例
//con.setValue(0)の場合
value is 0

//con.setValue("tmp")の場合
value is tmp
~~~
# 仕組みを解説
タイトルの通り、型消去(Type Erasure)という仕組みが肝です。
これは、javaにおけるジェネリクス型における仕組みです。

## よくあるジェネリクス型の説明
ジェネリクス型によって、
`Container<Object>` `Container<Integer>` `Container<String>`
のように、複数のクラスがコンパイラで作られる

という説明がよくあります。
が、これは正確には正しく**ありません**。

## 実際には
コンパイルの時点で型の情報は消え、実際には
`Container<Object>`
というクラスが使いまわされます。

これを**型消去**（**Type Erasure**）といいます。

## つまり、
`Container<String> con`という変数は、コンパイル後（実行時）には`Container<Object>`となっているわけです。

## 最初のコードを見返すと
前述の通りコンパイルは通ります。つまり、`con`は`Container<Object>`の変数として扱われます。

最初のコードは、次のように解釈できます。
~~~
Container<String> con=new Container<>();
//実行時には、Container<Object>として扱われる
//con.valueの型もObject

Integer i=0;
con.setValue(i);
//setValue(i)の中では
//con.value=(Object)value; が実行される
~~~
実行時には、コメントで書いたような処理になります。

型消去の仕組みのせいで、最初に示したコードも普通に動くのです。

# まとめ
本記事では、型消去（Type Erasure）の次の2つ特徴を利用しました。
- コンパイル後に型の情報は消える
- `Container<Object>`というクラスが使いまわされる

これによって、最初のコードは動くわけです。

ちょっとでも面白いな、不思議だな、と思っていただけましたか？

# 参考
java 公式ドキュメント
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

改訂2版 パーフェクトJava　井上 誠一郎・永井 雅人 (著)　技術評論社
pythonのbeautifulsoup4で、XPATHからhtml要素を取得する

# 結論
`lxml`モジュールを使用します。beautifulsoup4でパースしたデータを一度`lxml.html.HtmlElement`に変換することでXPATHからhtml要素を取得することができます。

# 前提
beautifulsoup4だけでなく、`lxml`もインストールする必要があります。`pip`などでインストールします。
```
pip install lxml
```

# サンプルコード
サンプルコード作成のために、下記のページを使用させていただきました。

https://scraping-for-beginner.herokuapp.com/ranking/

上記のページの各観光地の総合評価を取得しています。

```.py
from lxml import html
import requests
from bs4 import BeautifulSoup

def main():
    response = requests.get("https://scraping-for-beginner.herokuapp.com/ranking/")
    soup = BeautifulSoup(response.content, "html.parser")
    # 一度'lxml.html.HtmlElement'に変換する
    lxml_data = html.fromstring(str(soup))
    # XPathが指定できる
    u_ranks  = lxml_data.xpath("//div[contains(@class, 'u_rankBox')]/span[contains(@class, 'evaluateNumber')]")
    
    for u_rank in u_ranks:
        print(u_rank.text)

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

### 結果
```
4.7
4.7
4.6
4.5
4.5
4.4
4.3
4.3
4.2
4.1
```

以上です。
curlコマンドのTLS通信をWiresharkで復号する

# はじめに
　HTTPS通信はTLSで暗号化されるので，パケットキャプチャしても暗号化前の通信は解読できません。ただ，HTTPS通信の中身をやっぱり見てみたくなることがあります。このような場合，共通鍵（セッション鍵）をcurlの機能で記録し，Wiresharkに共通鍵を認識させることで，TLS通信の内容を解読できます。

# テスト環境
## キャプチャ取得環境
- ubuntu22.04
- curl 7.81.0 (x86_64-pc-linux-gnu) libcurl/7.81.0 OpenSSL/3.0.2 zlib/1.2.11 brotli/1.0.9 zstd/1.4.8 libidn2/2.3.2 libpsl/0.21.0 (+libidn2/2.3.2) libssh/0.9.6/openssl/zlib nghttp2/1.43.0 librtmp/2.3 OpenLDAP/2.5.14
- Wireshark 3.6.2 (Git v3.6.2 packaged as 3.6.2-2)
## キャプチャ解析環境
- wireshark(Windows版4.0.7)

# curlコマンド実行
- あらかじめ裏でWiresharkやtcpdumpを起動し，パケットキャプチャを開始します。
- SSLKEYLOGFILE環境変数に，共通鍵を保管するファイル名を設定してcurlコマンドを実行します。
```
$ SSLKEYLOGFILE=/path/to/key.log curl https://example.jp/
```
- パケットキャプチャを停止し，pcapng/pcapファイルとして保存します。
- SSLKEYLOGFILEで指定したパスに，key.logファイルが保存されたことを確認します。

# WiresharkでTLSを復号
- pcapng/pcapファイルをWiresharkで開きます。この時点では，TLSで暗号化された通信は「Application Data」の状態で，内容は分かりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457890/f1ae6a3f-ed2a-9531-46c5-c8d0a6189fd5.png)
- SSLKEYLOGFILEファイル（key.log）を読み込ませます。「編集」→「設定」→左メニューの「Protcol」で「TLS」を選択。"(Pre)-Master-Secret log filename"の「参照」をクリックし，key.logを指定して「OK」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457890/78dab5ae-cc0e-40cd-66c7-f2d5c765cfd6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457890/d0423db5-9bcd-c310-8cc6-da6b7ae509a1.png)
- Wiresharkの表示が，復号された状態に変わります。さきほどのNo15のパケットが，「TLSｖ1.3 Application Data」から「HTTP GET / HTTP/1.1」に変わり，通信内容を確認できるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457890/c0ca7ff5-d12a-0936-5d6f-34075fb42710.png)

# SSLKEYLOGFILEとは
　SSLKEYLOGFILEとは，TLSで使用される秘密情報をロギングする機能とログフォーマットです。[RFCにドラフト](https://www.ietf.org/archive/id/draft-thomson-tls-keylogfile-00.txt)提出されていますが，残念ながらexpiredでした。ただ，Expiredにはなったもののcurl，chrome,Firefoxなどに実装されています。

# 注意事項
- 通常の利用でSSLKEYLOGFILE環境変数を有効にするのは危険なので避けてください。通信経路を盗聴される，かつ保存したファイルが漏えいすると，TLSでの暗号化通信が解読されてしまうからです。

# 参考文献
[curl公式](https://everything.curl.dev/usingcurl/tls/sslkeylogfile)
[The SSLKEYLOGFILE Format for TLS](https://www.ietf.org/archive/id/draft-thomson-tls-keylogfile-00.txt)
[Reading sniffed SSL/TLS traffic from curl with Wireshark](https://davidhamann.de/2019/08/06/sniffing-ssl-traffic-with-curl-wireshark/)
[TLSの復号に用いる SSLKEYLOGFILE のフォーマット提案仕様](https://asnokaze.hatenablog.com/entry/2022/10/26/005331)
[【Wireshark/Tshark】ブラウザのTLS通信をキャプチャ](https://chigusa-web.com/blog/wireshark-setup/2/)
springdoc-openapi v2.1.0はByteArrayHttpMessageConverterが無いとUnable to render this definitionになる


# 現象
Spring Boot 3対応のついでに```org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0``` にバージョンを上げたところswagger-uiが下記の表示になり正常に動作しなかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31934/105c0dfa-cd28-5b24-4a5a-17011d28d798.png)

```
Unable to render this definition
The provided definition does not specify a valid version field.

Please indicate a valid Swagger or OpenAPI version field. Supported version fields are swagger: "2.0" and those that match openapi: 3.0.n (for example, openapi: 3.0.0).
```

# 解決方法
この現象が発生するのは```WebMvcConfigurer```で```HttpMessageConverter```をカスタマイズしているためなので、そこに```ByteArrayHttpMessageConverter```を追加する。

```java
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.clear();

    converters.add(new ByteArrayHttpMessageConverter());
    converters.add(new MappingJackson2HttpMessageConverter());
  }
}
```

公式ドキュメントにも同様の記述がある。

> 13.79. Why am i getting an error: Swagger UI unable to render definition, when overriding the default spring registered HttpMessageConverter?
> When overriding the default spring-boot registered HttpMessageConverter, you should have ByteArrayHttpMessageConverter registered as well to have proper springdoc-openapi support.
>
>    converters.add(new ByteArrayHttpMessageConverter());
>    converters.add(new MappingJackson2HttpMessageConverter(jacksonBuilder.build()));
>
>  https://springdoc.org/#why-am-i-getting-an-error-swagger-ui-unable-to-render-definition-when-overriding-the-default-spring-registered-httpmessageconverter から抜粋

# 原因
詳細までは調査してないがあるバージョンからjsonを```String```ではなく```byte[]```で返すようになったため、```ByteArrayHttpMessageConverter```が無いとエラーになるようだ。以下は該当部分 https://github.com/springdoc/springdoc-openapi/blob/main/springdoc-openapi-starter-webmvc-api/src/main/java/org/springdoc/webmvc/api/OpenApiWebMvcResource.java#L109 の抜粋。

```java
	public byte[] openapiJson(HttpServletRequest request, @Value(API_DOCS_URL) String apiDocsUrl, Locale locale)
			throws JsonProcessingException {
		return super.openapiJson(request, apiDocsUrl, locale);
	}
```
初めまして、アドミンKです。

お疲れ様です。

アドミンKと申します。

今回から、業務のため学習した内容を、この開発者blogを通してアウトプットしていこうと思います。

主にSalesforceに関連する保守・維持業務を行っておりますので、基本はSalesforce関連の知識を上げていくつもりではありますが、Salesforceに限らず、個人的に勉強になったな、と思ったことも記載していくつもりです。

自分自身の学習が目的ですが、まだSalesforceは日本に進出したばかりで、私のように学習に悪戦苦闘している方が多くいらっしゃると思いますので、そういった方に少しでもお役に立てるよう情報をまとめたいと思っております。

私自身、Salesforceの学習を行い始めたのも、エンジニアとして働き始めたのも、半年前とかなりの新参者ですので、先輩方にはご指導・ご鞭撻をしていただけますと幸いです。

今回はご挨拶と、投稿方法確認のため、以上とさせていただきます。
これからどうぞよろしくお願いいたします。
Inductive Relation Prediction by Subgraph Reasoning

## はじめに

ナレッジグラフにおけるリンク予測モデルの1つであるGraILについてまとめる．
本記事は，[Inductive Relation Prediction by Subgraph Reasoning](https://proceedings.mlr.press/v119/teru20a.html) に掲載されている内容に基づく．

## 背景

従来の埋め込みベースの手法は，知識グラフの基礎となる構成的な論理ルールを明示的に捕捉しておらず，また，学習時にエンティティの完全な集合を必要とする．
GraILは、局所的なサブグラフ構造を推論し，実体に依存しない表現を学習する．埋め込みベースのモデルとは異なり，GraILはinductiveであり，学習後に未知のエンティティやグラフに汎化することができる．

## モデル

モデルの構築には，サブグラフの抽出，ノードラベリング，GNNによるスコア計算の3つのステップをとる．

### サブグラフの抽出

2つのノードu, vからk-hop離れたノードの集合をN(u)，N(v)とする．
このとき，以下の条件を満たすノードのサブグラフを考える．

- $N(u) \cap N(v)$
- ノードu, vの両方からk-hop以内

### ノードラベリング

サブグラフ上のノードiに対して，$(d(i, u), d(i, v))$を考える．
ここで，$d(i, u)$はノードi, u間の最短経路である．
ノードu, v は，それぞれ $(0, 1)$, $(1, 0)$とそれぞれ表現する．
それぞれのベクトルに対して，$[OneHot(d(i, u)) \oplus OneHot(d(i, v))]$のようにone-hot表現にし，結合することによって各ノードをサブグラフ上のトポロジカルな位置として表現する．

### GNN によるスコア計算

#### Message-Passing Scheme [[Xu 2019](https://arxiv.org/abs/1810.00826)]

隣接するノードの表現を繰り返し集約し更新していくことで，ノードを表現する．
$N(t)$をノードtの隣接ノードの集合としたとき，ノードtの隣接ノードから集約された表現 ($a_t^k$)と，ノードtにおけるk層目の表現 ($h_t^k$) は以下のように与える．
このとき，$h_i^0$はノードラベリングによって得た特徴量で初期化する．

$$
a_t^k = AGGREGATE^k(\set{h_s^{k-1}: s \in N (t) }, h_t^{k-1} )
$$
$$
h_t^k = COMBINE^k(h_t^{k-1}, a_t^k)
$$

#### Attention [[Schlichtkrull 2017](https://link.springer.com/chapter/10.1007/978-3-319-93417-4_38)]

アテンションを追加し，AGGREGATE関数を次のように定義する．

$$
a_t^k = \sum_{r=1}^{R}\sum_{s \in N_{r}(t)} \alpha_{rr_tst}^k W_r^k h_s^{k-1}
$$

$R$: ナレッジグラフにおけるrelationの総数
$N_r(t)$: ノードtがrelation r で隣接するノードの集合
$W_r^t$: relation r における k層目のメッセージを伝達する変換行列
$\alpha_{rr_tst}^k$: ノードs, t間のrelation r のk層目のアテンションの重み

また，この重みは次のように与える．

$$
\alpha_{rr_tst}^k = \sigma(A_2^ks + b_2^k)
$$
$$
s = ReLU(A_1^k[h_s^{k-1} \oplus h_t^{k-1} \oplus e_r^a \oplus e_{r_t}^a ] + b_1^k)
$$

$e_r^a, e_{r_t}^a$: それぞれのrelationにおけるアテンションの埋め込み

#### Basis Sharing Mechanism [[Schlichtkrull 2017](https://link.springer.com/chapter/10.1007/978-3-319-93417-4_38)]

COMBINE関数は，次にように与える．
また，Edge Dropoutを行うことで，集約しつつエッジをランダムに削除する．

$$
h_t^k = ReLU(W_{self}^k h_t^{k-1} + a_t^k)
$$

$W_{self}^k$: 各層の変換行列

#### サブグラフの表現

L層のMessage Passingの後，サブグラフ上のノードの集合を $\nu$ として，サブグラフの表現は次のように与える．

$$
h_{G_{(u, v, r_t)}}^L = \frac{1}{|\nu|} \sum_{i \in \nu} h_i^t
$$

#### リンク予測におけるスコア

サブグラフの表現($h_{G_{(u, v, r_t)}}^L$)，対象ノードの表現 ($h_u^L$, $h_v^L$)，対象のrelationの埋め込み ($e_{r_t}$) を結合することで，次のようにスコアを定義する．

$$
score(u, r_t, v) = W^T[ h_{G_{(u, v, r_t)}}^L \oplus h_u^L \oplus h_v^L \oplus e_{r_t}]
$$

また，JK-Connection Mechanism ([Xu 2018](http://proceedings.mlr.press/v80/xu18c.html)) にように，断片的な層の表現を用いることで，パフォーマンスを向上させる．


## 学習

トリプルの先頭または末尾をランダムに別のエンティティと入れ替えることで，negative tripletをサンプルする [[Bordes2013](https://proceedings.neurips.cc/paper/2013/hash/1cecc7a77928ca8133fa24680a88d2f9-Abstract.html)]．
ロス関数を次のように与え，確率的勾配降下法によって学習を行う．


$$
L = \sum_{i=1}^{|\epsilon|} max(0, score(n_i) - score(p_i)+\gamma)
$$

$\epsilon$: 学習グラフにおけるエッジ/トリプレットの全ての集合
$p_i, n_i$: positive tripletと，negative triplet
$\gamma$: margin hyperparameter


## 終わりに

GraILと呼ばれるリンク予測モデルについてまとめた．
一方で，説明が不十分な点が残っており今後も追記していく．
DISM mount-imageコマンドでexFat上にマウントはできない

wimファイルのマウント等に使える、Windows標準搭載のDISMコマンド。マウントをするにはdism mount-image(以下略)で行うが、一つ発見した疑惑がある。

dism mount-imageでのマウント先は、exFatフォーマットのドライブを指定することはできない。いや、詳しく実験していないがおそらくNTFS以外は不可と思われる。なお、イメージファイル自体はどこに置いてあっても問題はない。

理由はアクセス権等が指定できないとダメとかそんなところなんでしょうか？しかし不思議なのは、なぜその仕様、現象を検索しても出てこないのでしょうか。。。
cscの作法 その420

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
automationでメモ帳、開いてhello.csをメニューをクリックしてセーブせよ。

# サンプルコード

```


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Automation;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace App
{

	class Program {
		static void Main(string[] args) {
			UIAutomationLib ui = new UIAutomationLib();
			Process notepad = Process.Start(@"notepad");
			Thread.Sleep(2000);
			notepad = ui.UpdateTargetProcess("メモ帳");
			AutomationElement notepadElement = ui.GetMainFrameElement(notepad);
			ui.Keyin(true, notepadElement, "using System; \n");
			ui.Keyin(true, notepadElement, "class Hello {{} \n");
			ui.Keyin(true, notepadElement, "   static void Main{(}{)}    {{} \n");
			ui.Keyin(true, notepadElement, "      Console.WriteLine{(}\"Hello, World\"{)}; \n");
			ui.Keyin(true, notepadElement, "    {}} \n");
			ui.Keyin(true, notepadElement, "{}} \n");
			ui.ClickElement(notepadElement, "Item 1");
			ui.Keyin(false, notepadElement, "a");
			string d = System.IO.Directory.GetCurrentDirectory();
			d = d + "\\hello.cs";
			ui.Keyin(false, notepadElement, d);
			ui.Keyin(false, notepadElement, "{ENTER}");
			notepad.CloseMainWindow();
		}
	}
}


```


以上。
いろいろなボードでArduinoでインラインアセンブラを使ってみる

# 参考

- https://qiita.com/TakeoChan/items/992026ec9e06337d97e7
- http://www.neko.ne.jp/~freewing/cpu/stm32_stm32f103c8t6_gcc_inline_assembler/

# 動かしてみたボード

- NUCLEO F303K8
- NUCLEO G070RB
- Seeed XIAO
- Raspberry Pi Pico（互換のRP2040ボード）

# 使ったコード

```cpp:asm_test.ino
void setup() {
  Serial.begin(9600);
  while (!Serial) {}
  Serial.println("Boot NUCLEO");

  int a=1, b=2, c=3; 

  Serial.print("a = ");
  Serial.print(a);
  Serial.print(" b = ");
  Serial.print(b);
  Serial.print(" c = ");
  Serial.println(c);

  // res = i + j;
  asm volatile (
     "ADD %[result], %[input_i], %[input_j]"
     : [result] "=r" (a)
     : [input_i] "r" (b), [input_j] "r" (c)
     );

  Serial.print("a = ");
  Serial.print(a);
  Serial.print(" b = ");
  Serial.print(b);
  Serial.print(" c = ");
  Serial.println(c);
}

void loop() {
}
```

実行例

```bash
$ arduino-cli compile --fqbn STMicroelectronics:stm32:Nucleo_32:pnum=NUCLEO_F303K8 asm_test
最大65536バイトのフラッシュメモリのうち、スケッチが11620バイト（17%）を使っています。
最大12288バイトのRAMのうち、グローバル変数が1184バイト（9%）を使っていて、ローカル変数で11104バイト使うことができます。

Used library Version Path                                                                                                   
SrcWrapper   1.0.1   /Users/numeru55/Library/Arduino15/packages/STMicroelectronics/hardware/stm32/2.5.0/libraries/SrcWrapper

Used platform            Version Path                                                                              
STMicroelectronics:stm32 2.5.0   /Users/numeru55/Library/Arduino15/packages/STMicroelectronics/hardware/stm32/2.5.0

$ arduino-cli upload --fqbn STMicroelectronics:stm32:Nucleo_32:pnum=NUCLEO_F303K8 asm_test
Found 'NODE_F303K8' at '/Volumes/NODE_F303K8'
Copying /private/var/folders/c_/wzylbygj0b9cc551z53rjr7r0000gn/T/arduino/sketches/AE97D6A7E80798B6833F891E3602AF0E/asm_test.ino.bin to /Volumes/NODE_F303K8...

$ arduino-cli monitor -p /dev/cu.usbmodem14103
Connected to /dev/cu.usbmodem14103! Press CTRL-C to exit.
Boot NUCLEO
a = 1 b = 2 c = 3
a = 5 b = 2 c = 3
^C
$
```
API Gateway→Lambda→DynamoDBとデータを受け渡す

# 背景
最近業務外でサーバレス系サービスに触れる機会が増えました。せっかくなので理解を深めようと考え、タイトルの3サービスを触ったのでそれについての備忘です。サクッと作成できるので、興味がある方はぜひお手元の環境でお試しください。なお、DynamoDBとLambdaの構築は慣れている方が多いので構築手順は省いています。本記事の内容は以下のUdemy講座を参考にしています。

https://www.udemy.com/course/aws-vlfc/

# 構築する内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/08d48572-2f8b-3843-c50c-6a6fcff12134.png)
# DynamoDBの用意
テーブル名は`users`として、パーティションキー`id`、`文字列`のみ設定します。
# Lambdaの用意
この後作成するAPI GWからデータを受け取り、DynamoDBに格納するコードです。
ランタイムは`Python 3.9`で、Lambdaのロールには`AWSLambdaBasicExecutionRole`と`AmazonDynamoDBFullAccess`をアタッチしています。
```python
import boto3
import json

dynamodb = boto3.client('dynamodb')

def post_users(requestJSON):
    dynamodb.put_item(
        TableName='users',
        Item={
            'id': {'S': requestJSON['id']},
            'name': {'S': requestJSON['name']},
            'age': {'N': requestJSON['age']}
        }
    )

def lambda_handler(event, context):
    # 受け取ったデータを文字列でなくJSONだと解釈
    requestJSON = json.loads(event['body'])
    post_users(requestJSON)
```

# API Gatewayの用意
API Gatewayはあまり経験がなかったので、細かく書いていきます。
### REST API作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/4f4bc5fe-3fd0-57cf-68dd-fa20c6de1d2a.png)
### リソースとメソッドの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/ea8cf914-765e-313a-5ee9-31a407ba22d3.png)
### 統合リクエストの編集
画面が遷移しますので、統合リクエストの編集を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/6646b83b-ae6e-d97c-39ba-98be424aba59.png)
クライアントから送るデータはそのままLambdaに受け渡すとエラーを吐いてしまうため、マッピングテンプレートを用いてLambda用にデータを整形します。
マッピングテンプレート名は`application/json`とし、内容は以下のように記載します。これでLambdaに`event['body']`の形でデータを渡すことができ、`KeyError`を回避できます。
```json
{
    "body" : "$util.escapeJavaScript($input.body)"
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/b33e0ce2-1811-7f71-c73c-c83c2f42a962.png)
### APIのデプロイ
作成したAPIはデプロイすることで、実際に使えるようになります。デプロイ後、サイドバーの`POST`を押します。画面に表示される、`/users`で終わるURLはすぐ使うので、メモをお忘れなく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/34212c2b-0c81-f142-a095-acf0bdb1233c.png)
これで全てのリソースの作成が完了しました。

# curlコマンドでデータを送る
下記コマンドを入力します。
-d以降は最初と最後以外の`"`に対して`\`でエスケープ処理を加えています。`ドメイン名`の部分は直前にコピーした`/users`で終わるURLを張り付けてください。
```bash
curl -X POST -H "Content-Type: application/json" -d "{\"id\":\"1000\",\"name\":\"Taro\",\"age\":\"22\"}" /usersで終わるURL

# 出力結果(Lambdaで返す値を設定していないためnull)
null
```

# データが格納されることを確認 
作成したDynamoDBの項目の中身を見て、格納されていれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986198/a37f61c2-96f1-e040-4116-c87f5a414049.png)

# 最後に
今回はAPI Gateway、Lambda、DynamoDBとデータを受け渡す仕組みを構築しました。本記事では内容を省いていますがAPI Gatewayを構築する中で、REST APIについての理解も深まったので勉強できてよかったです。ここまでお読みいただきありがとうございました。
【Rust】wasmでStringを含むstructを返したい場合「`std::marker::Copy` is not implemented for `String`」のエラー

## 概要
Rustでwasmを実装する際に、返り値としてStringを含むstructを返すような場合の対応メモです。
例えば以下のようなstructを実装した場合、``std::marker::Copy` is not implemented for `String``というエラーでコンパイルがエラーになります。なお、今回使用しているwasm-bindgenのバージョンは`0.2`です。

```rust
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct ResultResponse {
    pub success_flag: bool,
    pub text: String,
}
```

## 対応
[How declare pub struct with pub fields with wasm_bindgen attribute](https://github.com/rustwasm/wasm-bindgen/issues/3417)のissueの記事に、対応方法がいくつか紹介されています。個人的には、`#[wasm_bindgen(getter_with_clone)]`をstructに設定する対応が良いかなと思いました。
一応、wasm-bindgenのドキュメント[Exported struct Whatever Rust Types](https://rustwasm.github.io/wasm-bindgen/reference/types/exported-rust-types.html)
にも、`#[wasm_bindgen(getter_with_clone)]`の使用について紹介されています。

## 実装サンプル
以下の通り、structに対して`#[wasm_bindgen(getter_with_clone)]`を設定します。


```rust
use wasm_bindgen::prelude::*;

#[wasm_bindgen(getter_with_clone)]
pub struct ResultResponse {
    pub success_flag: bool,
    pub text: String,
}
```
【React Native】キーボードが表示されたときに要素を隠さないようにする方法



React Nativeでアプリを開発していると、テキスト入力時にキーボードが表示されると、そのキーボードによって画面下部の要素が隠れてしまうという問題に直面することがあります。この問題を解決するための一つの方法として、React Nativeが提供している`KeyboardAvoidingView`がありますが、その使い方が難しく、またiOSとAndroidの挙動の差異など、いくつかの問題点があります。

そこで今回は、`react-native-keyboard-aware-scroll-view`というライブラリを使った方法をご紹介します。

## 導入方法

まずはライブラリをインストールします。

```bash
npm install react-native-keyboard-aware-scroll-view
```

または yarn を使用している場合は

```bash
yarn add react-native-keyboard-aware-scroll-view
```

## 使用例

以下のように、`KeyboardAwareScrollView`コンポーネントを使って囲むだけで、子要素がキーボードに隠れることを防ぐことができます。

```tsx
import React from 'react';
import { TextInput } from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';

const App: React.FC = () => {
  return (
    <KeyboardAwareScrollView>
      {/* 他のUI要素... */}
      <TextInput placeholder="ここにテキストを入力" />
      {/* 他のUI要素... */}
    </KeyboardAwareScrollView>
  );
};

export default App;
```

## `react-native-keyboard-aware-scroll-view`のメリット

- iOSとAndroidの両方で一貫性のある結果を得られます。
- 自動的にビューがキーボードによって隠れないようにスクロールします。
- `extraScrollHeight`や`enableAutomaticScroll`などの追加のプロパティを用いて、より具体的な制御やカスタマイズが可能です。
- 特定の部分にのみ適用することが可能です。これにより、必要な領域だけを対象にしたより詳細な制御が可能です。

以上、React Nativeのキーボード表示時の問題を解決するための一つの方法をご紹介しました。`react-native-keyboard-aware-scroll-view`を使うことで、より簡単かつ柔軟にキーボードに対応したUIを実装できます。是非一度お試しください。
Linux PC を活用し、ファイルサーバ(Samba)を使う

# Linux PC をファイルサーバとして活用する

## やりたいこと
Linux(Ubuntu)PCにsambaをインストールし、別のLinux(Ubuntu)PCからファイルサーバにアクセスする

## 環境
OS：Ubuntu 20.04 LTS
(ファイルサーバPC、アクセスPCともに同じ)

## Sambaのインストール
```bash
sudo apt update
sudo apt upgrade
```
```bash
sudo apt install -y samba
```
## 共有ディレクトリの設定
共有ディレクトリ名を`share`として、以下の通りディレクトリを作成する
```bash
sudo mkdir /home/share
```
共有ディレクトリの権限を変更する
```bash
sudo chmod 777 /home/share
```
## 設定ファイルの編集
`smb.conf`を開き、次の内容を追記する
```bash
sudo nano /etc/samba/smb.conf
```
```
[share]
path = /home/share/
browsable = yes
writable = yes
guest ok = yes
read only = no
```
## ファイルサーバへアクセス
サーバーアドレスが192.168.0.100で、共有ディレクトリ名が"share"、ユーザー名が"username"の場合、次のように実行する
```bash
smbclient //192.168.0.XXX/share -U username
```
## ファイルのダウンロード
ファイルサーバにアクセスした状態で、下記コマンドを実行する
```bash
smb: \> get ファイル名
```
## ファイルのアップロード
ファイルサーバにアクセスした状態で、下記コマンドを実行する
```bash
smb: \> put ローカルファイルのパス
```
## ファイルサーバの接続終了
```bash
smb: \> exit
```
[flutter] alarmライブラリを使用してできる事できない事をまとめてみた。

## はじめに
今回は、flutterでアラーム機能を作る機会があったのでその際の知見を共有しようと思います。

現状flutterでアラーム実装に有用そうなライブラリはこの[alarm: ^1.1.7](https://pub.dev/packages/alarm)一択になるかなと思います。
※ios,android両方で実装する場合に限りの話です。

androidのみ実装であれば結構サクサクできそうなんですが、iosに関しては結構**沼**です。
なので今回はalarmライブラリを使用した際にできる事できない事をそれぞれまとめていこうと思います。


## 導入

ライブラリの導入は以下、[公式ドキュメント](https://pub.dev/packages/alarm)から各自行なってください。

ここでは、記載を省略します。

## how to use

まず、以下をmain関数の中に書いていきます。

```dart
void main()async {
await Alarm.init()
}
```

次に以下のようにAlarmSettingのパラメータをそれぞれ埋めていきます。


```dart
final alarmSettings = AlarmSettings(
  id: 42,
  dateTime: dateTime,
  assetAudioPath: 'assets/alarm.mp3',
  loopAudio: true,
  vibrate: true,
  fadeDuration: 3.0,
  notificationTitle: 'This is the title',
  notificationBody: 'This is the body',
  enableNotificationOnKill: true,
);
```

>id..それぞれのアラームを識別するための識別子です。
>dateTime..ここでタイマーが発現する時間を指定します。文字通りDateTime型で指定します。
>assetAudioPath..ここでアラームの音源を指定します。※音源の設定方法等は別途ググって見てください
>loopAudio..音源をループするかを決定します。
>vibrate..バイブレーションを付けるか決定します。
>notificationTitle..通知のタイトルを決定します
>notificationBody..通知の本文を決定します。
>enableNotificationOnKill..通知をタップした際にアラームをキルします。※なぜかうまく動作しない。。

その他のパラメータに関しても触って見てください。

## できない事１

###### アプリをタスクキルした際（バックグラウンド状態）に、アラームが鳴らない。

これは、アプリの仕様によっては割と致命的かもですね。。

これに関しては公式ドキュメントで実現できない事は**公言**されているのでこのライブラリでの実現は難しそうですね。。

どうしてもバックグラウンドで動作するアラームを作りたいのであれば、**一から自作するしかなさそうです。。**
気が向いたらそこら辺に関しても別記事でまとめようと思いうます。



## できない事２

###### 通知をタップした際に、アラームを止めることができない。

ios標準のアラームアプリでは通知をタップしたらアラームは止まる仕様になっていてそのように実装するのが自然かと思います。

ですがなぜかこれがうまくいきません。。

```dart
   enableNotificationOnKill: true,
   stopOnNotificationOpen: true,
```

ドキュメントを参照する限るここら辺のパラメータをtrueにすればいけそうなんですけどね。
stackoverflowなどで同じようなissueが報告されていたのでライブラリ自体の不具合なのかな。。っていう印象です。
このバグに関しては引き続き調査していくので、続報があればまた報告します。

## 
最後に
もし上記の不具合解決できましたよーみたいな事があれば、コメントいただけると非常に助かります！
最後までご覧いただいてありがとうございました。
現在のブランチを保留にして新たなブランチで作業をしたい[stash]

# 1.はじめに
作業中に別ブランチを切って作業したいときに`stash`を使用して現在のブランチでの変更を退避させることができます。
退避した変更をもとに戻して作業を再開することも可能です。

# 2.stashコマンド一覧
### 1.作業を退避させる
以下コマンドでメッセージをつけて変更を退避させることができます。
あとからみたときにわかりやすいメッセージをつけておくことをおすすめします。
```
$ git stash save "メッセージ"

このコマンドを使うと未追跡のファイルも退避できる。
$ git stash save -u "メッセージ"
```

### 2.退避した作業の一覧を表示させる
```
$ git stash list
```

### 3.退避した作業を戻す
```
$ git stash apply stash@{0}
```

### 4.退避した作業を消す
```
$ git stash drop stash@{0}
```

### 5.退避した作業の詳細を確認する
```
$ git stash show stash@{0}
```
以下コマンドで詳細まで確認できます。
```
$ git stash show stash@{0} -p
```
wire / drupal ってなんや？

Alpine.js を使うとか使わないとかで記事を探してたら出てきた。
よくわからないけど動的インターフェイスをコンポーネント化できるらしいので試してみる。

## クイックスタート
[ドキュメント](https://wire-drupal.com/docs/quickstart)通りに進める。

### インストール
```zsh
# モジュールインストール
composer require wire-drupal/wire
# モジュール有効化
drush en wire
# コンポーネント作成コマンド
drush generate wire
```
コマンドを叩くと以下の内容のやり取りがある
```
Module machine name [app]: (システム内部名称)
 ➤ counter

 Wire label [Example]: (モジュール一覧画面のラベル)
 ➤ Counter

 Wire ID [counter]: (多分 twig とかで使用するときようのID)
 ➤ 

 Wire class [Counter]: (Class名)
 ➤ 

 Inline template [No]: (Yes にすると PHP で HTML(twig)を直書きできる. Twig を使いたいから基本Noで良さそう)
 ➤ 

 Would you like to inject dependencies? [No]: (DIするサービスはあるかどうか)
 ➤ 
```

`Wire ID` や `Wire class` はシステム内部名称に合わせて自動で補完してくれる。
DI は Yes とするとその後 DIするサービスを入力できる機能まで付いていた。

### ファイルの中身
対話が終わると以下２つのファイルがカスタムモジュールディレクトリ下に生成された。

```Counter.php
/**
 * Implementation for Counter Wire Component.
 *
 * @WireComponent(
 *   id = "counter",
 *   label = @Translation("Counter"),
 * )
 */
class Counter extends WireComponent {

  public function render(): ?View {
    return View::fromTpl('counter');
  }

}
```
```counter.html.twig
<div>
    ...
</div>
```

なぜか info.yml が生成されなかったので手動で作って有効化する必要があった。

### コンポーネントを Twig ファイルに含める
twig ファイルで `wire()` 関数を呼び出すことでコンポーネントを使用できる。

```twig
{{ wire('counter') }}
```

コントローラーのレンダリング配列に `#type` と `#id` を指定することで表示することもできる。

### カウンター機能を追加
一旦コピペで確認

```Counter.php
class Counter extends WireComponent {

  public int $count = 0;
  
  public function increment() {
    $this->count++;
  }
  
  public function render(): ?View {
    return View::fromTpl('counter');
  }
  
}
```
```counter.html.twig
<div style="text-align: center">

  <button wire:click="increment">+</button>
  
  <h1>{{ count }}</h1>
  
</div>
```

結果

![スクリーンショット 2023-07-22 16.56.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1323938/9a39376a-7d52-ad7b-83b0-491968b28047.png)

## まとめ
- vue でいう script を PHP で書いて template は twig っぽい感じで書ける。
- テンプレート側のイベントをリッスンしてPHPで更新やらできるっぽいので対話型のサイトも簡単に作成できそう。
- alpinejs が読み込まれてるけど書き方ちょっと違うし、これは一体なんなんだろう。謎が深まった。
JUMAN++をWindows環境で動かしてみる

### はじめに
京大の研究室が公開しているBARTの日本語Pretrainedモデルの利用を検討しています。
JUMAN++で形態素解析した結果を渡す必要があるため、まずはJUMAN++を導入してみます。

https://nlp.ist.i.kyoto-u.ac.jp/?BART%E6%97%A5%E6%9C%AC%E8%AA%9EPretrained%E3%83%A2%E3%83%87%E3%83%AB

### インストーラを取得する
``jumanpp-2.0.0-rc3.tar.xz`` をダウンロードします。

https://github.com/ku-nlp/jumanpp/releases/tag/v2.0.0-rc3

### Visual Studio Community をインストールする

ダウンロードした資材をビルドするために、Visual Studio 2022をインストールします。

https://visualstudio.microsoft.com/ja/vs/community/

インストール時に、以下の2つの項目を選択してください。
- 「ワークロード」>「C++によるデスクトップ開発」
- 「個別のコンポーネント」>「Windows用 C++ CMakeツール」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883662/e66dbbd7-dc36-1e98-8a1e-ab42c77e4bb6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883662/b5df0b27-0633-a4d5-e1c7-4dde0e1ed00c.png)

### Cmakeでビルドする
「x86 Native Tools Command Prompt for VS 2022」を開き、以下を実行します。
```console:ビルド
$ cd ●●●/●●●/ ... /jumanpp-2.0.0-rc3
$ mkdir cmake-build-dir
$ cd cmake-build-dir

$ cmake ..
$ cmake --build . --config Release
$ ctest -C Release --output-on-failure
```

### 実行用のディレクトリを作成する
以下のファイルを取得して、Cドライブ直下に配置します。
- ``jumanpp-2.0.0-rc3\cmake-build-dir\src\jumandic\Release\jumanpp_v2.exe``
- ``jumanpp-2.0.0-rc3.tar\jumanpp-2.0.0-rc3\model\jumandic.conf.in``
- ``jumanpp-2.0.0-rc3.tar\jumanpp-2.0.0-rc3\model\jumandic.jppmdl``

```console:フォルダ構成
C:jumanpp
│  jumanpp_v2.exe
│
└─libexec
        jumandic.conf //jumandic.conf.inをリネームする
        jumandic.jppmdl
```
フォルダを作成したら、環境変数PATH に ``C:jumanpp`` を追加してください。

### jumandic.confを編集する

``jumandic.conf`` を開き、modelのパスを変更します。
```conf:jumandic.conf
--model=C:/jumanpp/libexec/jumandic.jppmdl
--rnn-nce-bias=5.62844432562
--rnn-unk-constant=-3.4748115191
--rnn-unk-length=-2.92994951022
--feature-weight-perceptron=1
--feature-weight-rnn=0.0176
```

### 実行用のバッチファイルを作成する

実行用のバッチファイル``jumanpp.bat``を作成して、``C:jumanpp`` に配置します。
```bat:jumanpp.bat
@echo off
jumanpp_v2 --config=C:\jumanpp\libexec\jumandic.conf %*
```

これで、コマンドプロンプトからJUMAN++ を実行できるようになりました。


### pyknpをインストールする
JUMAN++ をpythonで利用するために、pyknpをインストールします。

https://github.com/ku-nlp/pyknp

```console:install
$ pip install pyknp
```

### pyknpの中身を修正する

``Python3\Lib\site-packages\pyknp\utils\process.py`` を修正します。
Windows環境で動かすために、signalで書かれているコードを書き換えます。

```python:修正箇所 (L3～L4)
#import signal
import threading
```
```python:修正箇所 (L75～L79)
        #signal.signal(signal.SIGALRM, alarm_handler)
        #signal.alarm(self.process_timeout)
        alarm = threading.Timer(self.process_timeout, alarm_handler)
        alarm.start()
```
```python:修正箇所 (L88～L90)
        finally:
            #signal.alarm(0)
            alarm.cancel()
```

### サンプルコード
以下のようなコードで、分かち書きができるようになりました。

```python:sample.py
from pyknp import Juman

# 入力文
text="すもももももももものうち"
# 改行削除、半角スペースを全角スペースに変換
clean_text=text.replace('\n', '').replace(' ', '　')

list=[]
jumanpp = Juman(command='jumanpp_v2', option='--config=C:/jumanpp/libexec/jumandic.conf')
mrphs=juman.analysis(clean_text)
for m in mrphs:
    list.append(m.midasi)

print("　".join(list))
```

### 参考文献
https://trend-tracer.com/juman/

https://trend-tracer.com/windows-juman/

https://ensekitt.hatenablog.com/entry/juman
【AI】JupyterAIをwindows端末で動かす手順【2023/07/22版】

# はじめに
[Jupyter AI](https://jupyter-ai.readthedocs.io/en/latest/users/index.html)は、JupyterLab3.6.5でしか動かないようです。(2023/07/22現在)
[JupyterLab](https://github.com/jupyterlab/jupyterlab) -> Jupyter AIの公式手順に従って環境構築をしても動かないので、手順を残します。

# 前提
* PowerShell等、ターミナル操作の知識が必要です
* 使用するPythonは、バージョン3.8~3.11である必要があります
    * 3.11では動かないみたいな投稿も見た気がするので、3.10までの方が安全かもしれません
* 本記事ではOpenAIのAPIをモデルとして使用します
    * OpenAIのアカウントを作成し、[OpenAI_API_KEYを作成](https://platform.openai.com/account/api-keys)しておいてください

# 失敗例
* ```pip install jupyterlab```を実行した場合
    * JupyterLab4系が入り、JupyterAIが対応していないためchat用タブが表示されません
* [jupyter公式のdockerイメージ](https://hub.docker.com/r/jupyter/minimal-notebook/tags?page=1&name=lab)を使おうとした場合
    * jupyter4系を使用した場合、上記と同じくchat用タブが表示されません
    * jupyter3系は3.6.3までしか用意されておらず、これを使用した場合実行時エラーが発生します


# 手順
## 1. venv環境の構築
* まず、作業したいディレクトリを用意します
* その後下記コマンドでvenv環境を作成、ログインします

```bash
python -m venv venv
./venv/Scripts/activate
python.exe -m pip install --upgrade pip
```

## 2. JupyterLab本体のインストール
JupyterLab本体をインストールします。
下記は、執筆時点の最新である3.6.5のインストールコマンドです。
```bash
pip install jupyterlab==3.6.5
```

## 3. AI機能のインストールと、環境変数の設定
```bash
pip install openai jupyter_ai
$Env:OPENAI_API_KEY={作成したAPIキー}
```

## 4. JupyterLabの起動
```bash
jupyter lab
```

# 結果
![jupyterAI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389892/a0b38469-f415-8d57-96da-f8628bc0ace4.jpeg)
Larave リレーション

laravelのリレーションのやり方のメモとポイントになるところを備忘録として書き残す。


今回は、postsという投稿のテーブルに、laravelのauthの標準のuserテーブルをリレーションする。
イメージはpostsの投稿が、どのユーザーによって投稿されたのかリレーションする。

まずは、テーブルの設計でのポイントから。
postテーブルとuserテーブルの関係は以下のようになる。

<table border=1>
<tr>
<td>posts</td>
<td>主テーブル</td>
</tr>

<tr>
<td>users</td>
<td>従テーブル</td>
</tr>
</table>

postテーブルに、投稿者のユーザーをリレーションするために外部キーをカラムに必ず追加する。
そして、この外部キーのカラム名だが自由に名付けることはできない。<font color="Crimson">ルールに従って名付けないと
リレーションが機能しない。下記のような名前の付け方をする。</font>

```
従テーブル名(単数系)_id
```

今回は、usesテーブルが従う￥テーブルになるので外部キーは"<b>user_id</b>"となる。
誤ってテーブル名をそのまま(複数形のsがついた名前)にすると動かないので注意。

続いて、リレーションの設定をするためにモデルを作成し設定する。
コマンドでモデルを作成する。
ここでも名前の付け方に注意。<font color="Crimson">モデル名の先頭は大文字で、単数系(語尾sはつけない)であること。</font>

```
php artisan make:model Post
```

モデルが作成できたら以下のように設定する。

```php:Post.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    //追記
    public function user(){
        return $this->BelongsTo('App\Models\User');
    }
    
}


```
ここでも関数の名前の付け方に注意がある。
<font color="Crimson">リレーションするテーブルの単数系の名前にすること。</font>
これで、postsテーブルにusersテーブルの情報が紐付けできた。

コントローラでDBデータとってくる際は、下記のような記載に書く。
(※自分はAPIで開発しているのでjsonを返すようになっている)
```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Post;

class PostController extends Controller
{

    function index(Request $request){
        $posts = Post::with(['user'])->get();
        return response()->json($posts);
    }


}
```
withメソッドを使い、引数にモデルで書いた関数の名前を書く。
これでpostsテーブルのデータにリレーションしているusersテーブルのデータを
一緒に引っ張ってこれる。


以上
作業ブランチを最新にする手順

### 1. masterブランチへ移動
```
git checkout master
```

### 2. masterを最新に更新
```
git pull origin master
```

### 3. 開発用のブランチへ移動
```
git checkout 開発用ブランチ名
```

### 4. masterの内容を取り込む
```
git merge master
```

### 5. 取り込んだものをリモートにpush
```
git push origin 開発用ブランチ名
```
【Java】学習記録②（入力値の受け取り）

## 文字列データの受け取り
```Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String text = scan.next();
        System.out.println(text);
    }
}
```

## 整数データの受け取り
```Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int number = scan.nextInt();
        System.out.println(number);
    }
}
```

## Scannerのcloseについて

Scannerは最後にcloseメソッドの呼び出しを期待されている。
一度closeしてから再度標準入力しようとしてもエラーが出てしまう。

ただ、プログラミング全般に通じる考え方や作法として、closeメソッドを記述する必要がある。
Rustで、&str, String, char関係なく「とにかく文字を受け取る」関数を作るには、impl ToStringを使おう

Rustには様々な型があり、「文字を扱う」とカテゴライズするだけでも、`&str` `String` `char` `Cow<'_,str>`など様々な型で扱うことができます。

これらを単に比較したり、特定の型に変換する場合は、`impl ToString`を使うと簡単に書けます。

例えば、何らかの文字を受け取って、それが同一かどうかを確かめる関数は、以下のように書くことができます。

```rust
fn cmp(a: &impl ToString, b: &impl ToString)-> bool{
  a.to_string() == b.to_string()
}
```
こう書くことで、引数`a` `b`には、`ToString`トレイトを実装しているどのような型も受け取ることができます。
※`ToString`を実装しているデータ型は[こちら](https://doc.rust-lang.org/std/string/trait.ToString.html)を参照

これは、引数aと引数bの型が違う場合に。非常に便利です。
通常、例えば`a: &str`と`b: char`を比較する場合、`a == b.as_str()`など、相手の型に合わせて変換してやる必要があります。

この関数では、`&str` `String` `char` `Cow<'_,str>`などは、すべて`ToString`トレイトを実装していることを利用し、一度`String`に変換してやってから比較を行います。

そのため、`a` `b`それぞれにどのようなデータ型が渡されようが、`to_string`を使ってあとは好きに比較なり変換なりすることができます。

Rust上級者の方からすると、Rust的なお作法とは少々異なっているので、色々思うところがあるかもしれませんが、まずは「とにかく動くコード」を書くことが大切です。

メモリ最適化やパフォーマンスの改善は、リファクタリングで行うべきです。

※事実と異なっている部分や、もっと良い方法があれば、コメントにてご指摘ください。
Prevent prompting on Dein.vim installer for automation

<!-- Prevent prompting on Dein.vim installer for automation-->

![dein.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/86a0f574-13de-eded-5960-4e20f7136680.png)

## Solution with custom parameters, suppressing promptings

```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Shougo/dein-installer.vim/master/installer.sh)" - --overwrite-config "$HOME/.cache/dein" --use-vim-config
```

## Basic Installation as formally described, introduces promptings

https://github.com/Shougo/dein-installer.vim

```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Shougo/dein-installer.vim/master/installer.sh)"
```

## 説明

後者の Basic Installation では実行時に数回のプロンプトが表示され、インストールオプションの選択を求められます
しかしこのような対話式は、ansible 等による自動化されたインストールや設定タスクの一つとして組み入れるうえでは許容できません。なので何らかの方法で抑止する必要が出てきます

[install.sh](https://raw.githubusercontent.com/Shougo/dein-installer.vim/master/installer.sh) を見たところ幸いにも上記 Solution のようにすれば良いように配慮されていることがわかりました ※2023/07/22時点

オプションの内容は適宜調整すればよいでしょう。 前者で示した例は vim 用の設定になります。　neovim を使う場合は --use-neovim-config に変える必要があるようです
英単語を使いこなしたい。

## はじめに
- 開発の仕事をしていて思うことは「上手な名前をつけられない」ことです。
- 同僚にもよく注意を受けます。 
- Qiitaでよく読まれている記事を見つけたので、読みました。

## 読んだ記事１
https://qiita.com/Ted-HM/items/7dde25dcffae4cdc7923

- 分量が多すぎて一度では読みきれませんでした。
- 単純な日本語訳だけではなく、ニュアンスを掴まないとだめなんだと感じました。
- この本からの学び
    - 意味が広義で”使ってはいけない言葉”があることを知る。
    - 意味を絞る→単語の選択、接頭辞、接尾語
    - 品詞を意識して使う
    - 対義語を用意する


- また、読んでいてなるほどと思った部分を引用いたします。

> clear / delete
>  中身だけ消すのが clear。
>  外側も含めてすべて削除するのが delete。

## 読んだ記事2
https://qiita.com/jnchito/items/459d58ba652bf4763820#%E3%82%84%E3%81%A3%E3%81%A6%E3%81%84%E3%81%84%E3%81%93%E3%81%A8%E3%81%A8%E3%81%84%E3%81%91%E3%81%AA%E3%81%84%E3%81%93%E3%81%A8%E3%81%AE%E5%8C%BA%E5%88%A5%E3%81%AF%E3%82%8F%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%A7%E3%82%82%E5%83%95%E3%81%AF%E6%97%A5%E6%9C%AC%E4%BA%BA%E3%81%AA%E3%82%93%E3%81%A0%E3%82%88

- 品詞の重要性を訴えてくれた記事でした。
- 英語の勉強は実施中ですので、勉強の要素に組み込みたいなと思います。

- また、英語の類義語を調べる癖をつけたいなと思いました。
https://www.thesaurus.com/browse/collapse



## 明日から
- 命名を後回しにしない。
- こまめに調べる。


##　終わりに
- 対義語で、横方向（`landscape`）、縦方向（`portrait`） があります。
- これらフランス語で、絵を書くときに
    - 風景はキャンバスを横方向に置く→`landscape`
    - 肖像画はキャンバスを縦方向に置く→`portrait`
- スマホのポートレート撮影も肖像画っぽく写すからなんだと納得しました。
Post manのレスポンスで401が返ってきた。

## はじめに
- 社内での開発中（open api 3.0を使って新規APIの作成みたいな作業）の話。
- open api を定義し、コード生成し、postmanでリクエストを投げたら、401レスポンスが返ってきた。 

## 401 Unauthorized とは

401 Unauthorizedは適切な認証情報を与えずリクエストを行った状態。

以下は、書籍「webを支える技術」から引用しています。

```
# リクエスト
POST /test HTTP/1.1
Host: exaample.jp

# レスポンス
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Example.jp"
```


## 401レスポンスの原因
- Post manのHeaderに認証キーを入れなかったため。
- 元々の定義でbearer認証が設定されており、tokenを入れたら行けた。

## open api 3.0に認証に関して
- open api 3.0には主に以下に三種類の認証を設定できる
    - Basic Authentication　
    - API　Keyｓ 
    - Bearer Authentication(also called token authentication)
- ちなみに「bearer」は「持ってくる」的な意味があり、仕様書にもそんなニュアンスで書いてある→The name “Bearer authentication” can be understood as “give access to the bearer of this token.” 

引用：[swagger](https://swagger.io/docs/specification/authentication/bearer-authentication/)

## 定義方法、認証方法

- opan api の定義方法
```
openapi: 3.0.0
...
# 1) Define the security scheme type (HTTP bearer)
components:
  securitySchemes:
    bearerAuth:            # arbitrary name for the security scheme
      type: http
      scheme: bearer
      bearerFormat: JWT    # optional, arbitrary value for documentation purposes
# 2) Apply the security globally to all operations
security:
  - bearerAuth: []         # use the same name as above
```

- post manではHeadersのKEYに`Authorization`、VALUEに`Bearer <token>`を記述する。


## その他
- 記事を書きながら「　realm」という単語が気になったので調べてみた。
    - realm 
        - 訳：領域・範囲・分野
        - 原義：「王国（の領土）」「領地」など君主の支配が及ぶ範囲。
    - IT用語のrealm
        - 認証情報、アクセス権、セキュリティポリシーなどが適用される範囲
        - 使い方→「利用者はシステムにログインすると、当該レルム内にある機器やサービスにアクセスできる。」
 
参考：[レルム](https://e-words.jp/w/%E3%83%AC%E3%83%AB%E3%83%A0.html)
踏み台経由でK8s Serviceへポートフォワードするのどうするんだっけという時のトラの巻

## やりたいこと
こんな感じの時にK8sのServiceへPCからアクセスした。（Grafanaとか）

```
PC -SSH(バッチ)-> Basion(共有) -SSH(鍵認証)-> Batsion(kubectl用) -> K8s
```

## やり方

バックグラウンド処理もできるが、止める時に他の人のプロセス止めると面倒なのでフォアグラウンドで処理する。

1. 【Batsion(kubectl用)】K8sへポートフォワード

    ```
    $ kubectl get svc xxx -n xxx
    ポートフォワード先のポートを確認する
    
    $ kubectl port-forward --namespace xxx svc/xxx 9090:【SVC Port】
    ```

1. 【Basion(共有)】Batsion(kubectl用)へポートフォワード

    ```
    ssh -N -L 8080:localhost:9090 【Batsion(kubectl用) IP】
    ```

1. 【PC】TeratermでSSH転送

    ```
    コントロール -> SSH転送 -> 追加
    ローカルのポート 8080
    リモート側のホスト localhost
    ポート 8080
    ```

1. 【PC】ブラウザでアクセス

    ```
    localhost:8080
    ```
Github Pagesでwebサイトを公開する

## 目的
webサイトの公開方法について悩んだ時に、友人からgithub pagesがあるよと言われたので、今回はそれを使ってみようと思う

## 設定方法
### 1. まずはリポジトリを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/672d2c3a-6bf3-2655-d8fa-6db01b55ada8.png)

**公開URLについて**
公開方法は2パターン
- https://アカウント名.github.io
- https://アカウント名.github.io/リポジトリ名

### 2.  htmlファイルを作成
とりあえず作ってみる
```index.html
<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8">
  <title>はじめてのHTML</title>
 </head>
 <body>
   <h1>HTML</h1>
   <p>Hyper Text Markup Language の略でウェブページを作成するための言語。</p>
 </body>
</html>
```

### 3. push
```bash
git init
git config --global user.email "XXXXXX@gmail.com"
git config --global user.name "shoma564"

git remote add origin git@github.com:shoma564/REPOSITORY.git
git remote set-url origin git@github.com:shoma564/REPOSITORY.git

git add *
git commit -m "first commit" 
git branch -M main
git push origin main
```

## 4. ページの公開設定(1)
setting → Pages
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/dcbd844a-18a9-fc16-27e3-2fde3c2e2a65.png)

## 5. ページの公開設定(2)
sourceを```Deploy from a branch```に設定。
Branchを```main```と```/(root)```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/15a62cbd-21ea-e45d-73e0-ffdbf3005545.png)

## 6. 設定の保存
Saveボタンをクリック。以下の画面が表示されたら設定完了




| 設定事項 | パラメータ   |
| -------- | --------    |
| アカウント名 | shoma564 |
| リポジトリ   | sin-matsuri |


以下のURLにアクセスすれば完了
- https://shoma564.github.io/sin-matsuri/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/71b697b1-aedb-7c38-512c-bd62144bb6cc.png)





## htmlファイルを別のフォルダに置きたい場合
1. docsフォルダを作成
2. docsフォルダ内の
3. branchの設定を```main```で```/docs```に変更
4. ```Save``` ボタンをクリック

5分ぐらい待つと更新される
イカリング3をPCブラウザで簡単に閲覧できるようにする方法

# はじめに

初めまして。きなあんです。Qiita初投稿です。

今回は、イカリング3をPCブラウザで簡単に閲覧できるようにする方法を他の人にも共有したいと思って記事にまとめることにしました。

# 参考にした記事

イカリング3をPCブラウザで閲覧する方法については下記の記事にとても分かりやすく記載されていました！
s3sの導入方法について書かれた記事ですが、最後のほうに「イカリング3をPCブラウザで閲覧する方法」も記載されています！

https://nerune-jp.com/splatoon3-statink/

ただ、実際にこの方法を試してみたところ、思った以上にgtokenの期限切れが早かったので、簡単にgtokenを取得する方法を共有したいと思います。

# gtokenをワンクリックで取得する方法

### 前準備

上の記事に従ってs3sを使えるようにしておいてください。

### pyperclipのインストール

コマンドプロンプト等で下記のコマンドを実行してpyperclipをインストールしてください。

```shell:copy_gtoken.cmd
pip install pyperclip
```

### 実行ファイルの作成

s3sをcloneしたフォルダ内に下記の2ファイルを作成してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3509311/12b5ff75-01ae-ab61-8b4d-18159a8b31cb.png)

```shell:copy_gtoken.cmd
@echo off
python copy_gtoken.py
echo gtoken copy completed!
pause > nul
```

```python:copy_gtoken.py
import s3s
import pyperclip

def main():
	# トークンを更新する。
	s3s.prefetch_checks(printout=True)

	# トークンをクリップボードにコピーする。
	pyperclip.copy(s3s.GTOKEN)

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

### copy_gtoken.cmd を実行する。
あとは copy_gtoken.cmd を実行するだけでクリップボードにgtokenがコピーできるようになります！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3509311/dce28c40-d132-43a2-fdbf-b1eb77a67403.png)

以上。
Gateboxの人感センサーでサクッとゲームを作る

Gateboxの人感センサーを使ってゲームを作りました！！
こちらの書籍を元ネタにネコが矢をよけるゲームにしました。

#### [Unityの教科書](https://www.sbcr.jp/product/4815606657/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502127/eb706a65-a3a1-71b8-d1d6-e6b316e17951.png)

## コーディング

お作法でレシーバを登録します。

```C#
    void Start()
    {
        HumanSensor.RegisterListener(gameObject.name, "GateboxHumanSensorFunc");
    }

```

センサーの検知はBooleanで処理しています。
こちらの処理はセンサーの状態が変化しないと再処理されないので、移動はUpdateで行います。

```C#
    public void GateboxHumanSensorFunc(string message)
    {
        // Parse
        HumanSensor.Result result = JsonUtility.FromJson<HumanSensor.Result>(message);
        GameObject.Find("MoveText").GetComponent<Text>().text = "センサーの状態\n左：" + result.left + "右：" + result.right;

        // Move Player
        if (result.left == "true" && result.right == "false")
        {
            leftSensor = true;
            rightSensor = false;
        } else if (result.left == "false" && result.right == "true")
        {
            leftSensor = false;
            rightSensor = true;
        } else
        {
            leftSensor = false;
            rightSensor = false;
        }
    }
```

センサーのBooleanに応じてネコを移動させます。
（左センサー -> 左移動 / 右センサー -> 右移動）
ポジションの上限 / 下限は良しなに。

```C#
    void Update()
    {
        // Left Move
        if (leftSensor && !rightSensor)
        {
            if (transform.position.x > -4.0f)
            {
                transform.Translate(moveX * (-1f), 0, 0);
            }
        }

        // Right Move
        if (!leftSensor && rightSensor)
        {
            if (transform.position.x < 4.0f)
            {
                transform.Translate(moveX, 0, 0);
            }
        }
    }
```

## いざ、実行

良い感じに動いています。
結構激しく運動する必要があります！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502127/bd6cb30b-d8db-f6e9-9d46-d32c194e8dc4.png)
MicroPython で RP2040 の GPIO レジスタを直接みてみる

# GPIOから値を読んでくる

P23の値を読んでみます

```main.py
from micropython import const

IO_BANK0_BASE = const(0x40014000)
GPIO23_STATUS = const(IO_BANK0_BASE + 0x0b8)
BIT_INFROMPAD = const(17) # input signal from pad

import machine

print( ( machine.mem32[GPIO23_STATUS] >> BIT_INFROMPAD ) & 1 )
```

データシート `2.19. GPIO` を読みます。制御レジスターの先頭アドレスが書いてあり，さらに各GPIOには CTRL と STATUS というレジスターがあるようです。

さらに STATUS レジスターの17ビット目，`INFROMPAD input signal from pad,` を読めば良いようです。

データシート `2.19.4. Pad Fig. 37` には， `Input Enable` というスイッチがありそうなのですが，制御レジスターのページには見当たりませんでした。デフォルトでPadの値は読めるようです。

# GPIOに値を書く

P25になにか書いてみます

```main.py
from micropython import const

# datasheet 2.1.2 Atomic Register Access

ATOMIC_XOR   = const(0x1000) # : atomic XOR on write
ATOMIC_SET   = const(0x2000) # : atomic bitmask set on write
ATOMIC_CLEAR = const(0x3000) # : atomic bitmask clear on write

IO_BANK0_BASE = const(0x40014000)

GPIO25_CTRL   = const(IO_BANK0_BASE + 0x0cc)

BIT_DRIVE_OUTPUT = const(8)

import machine

# [13:12] OEOVER to 0x3 enable output
machine.mem32[GPIO25_CTRL+ATOMIC_SET] = 0b11 << 12

# [9:8] OUTOVER to 0x2 drive out low or 0x3 drive out high
# -->> [9] OUTOVER to 1
machine.mem32[GPIO25_CTRL+ATOMIC_SET] = 1 << 9

machine.mem32[GPIO25_CTRL+ATOMIC_SET] = 1 << BIT_DRIVE_OUTPUT # for set 1
machine.mem32[GPIO25_CTRL+ATOMIC_CLEAR] = 1 << BIT_DRIVE_OUTPUT # for set 0
machine.mem32[GPIO25_CTRL+ATOMIC_XOR] = 1 << BIT_DRIVE_OUTPUT # toggle
```

同様に GPIO25 の CTRL レジスターにアクセスします。
最終的に [9:8] の2ビットに値を書くのですが， drive output low または drive output high の場合は9ビット目は１で固定なので，上記では先にセットしています。

また，RP2040は `2.1.2 Atomic Register Access` という機能があり，特定のビットを操作できます。面白いですね。

ここでは SET で 1 となり， CLEAR で 0 になって， XOR で 1 に反転しています。 

# おしまい

RP2040のGPIO制御をデータシート見ながら試してみました。
もっと先ではアセンブラでアクセスしたいなと思っているのですが，その前に扱い方を MicroPython で試しながら習得した感じです。いろいろ簡単に試せてよかったです。

参考

- https://zenn.dev/parityc3/articles/a9ae5d65e1f30b