OmniAICreator/Qiita-1.07M huggingface dataset:
VSCode の C# (拡張機能) を v1.25.0 に更新したらアウトラインが表示されなくなった

## 環境
Visual Studio Code v1.72.2
C# (拡張機能) v1.23.2 → v1.25.0 に更新

## 症状
VSCode の拡張機能である `C#` を `v1.25.0` に更新してからスクリプトを開くと、↓ の画像のように「ドキュメント '○○.cs' にシンボルが見つかりません」と表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246559/cb9a9ee7-48e0-1561-fbaf-7875549d8d0c.png)

また、関数やフィールドの定義に移動することが出来なくなっていました。


## 対処
拡張機能 `C#` のバージョンを、更新前の `v1.23.2` に戻したところ、各種不具合が直りました。

1. VSCode から C# の拡張機能を開き、設定アイコン → 「別のバージョンをインストール」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246559/de5bed72-c0e8-aa38-ad4d-d299bfe09697.png)
1. 「1.23.2」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246559/2755839e-8ea1-0169-a8da-17d8b9ab52b2.png)
1. 「再読み込みが必要です」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246559/7ff1374c-5356-90e4-672e-39ba634c9c4a.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246559/6a048af5-fda9-8479-f148-bb6986de57d8.png)

## その他
C# v1.24 台でも大丈夫なのかな…?
 (追記) v1.24.3 でも問題なく動作しました。
Javaで何か作ってみる(2022/10/30 Day10)

## 今日やった事
- 自分の[GitHub](https://github.com/takamatsuryota3)の整理を試みた。
## 参考にしたもの
- [Gitの運用方法の有名な３パターンについての考察 | こへいブログ](https://kohei.life/git-flows/)
- [84:リポジトリのルートディレクトリはシンプルに構成する](https://jisou-programmer.beproud.jp/%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%A7%8B%E6%88%90/84-%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%88%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AF%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AB%E6%A7%8B%E6%88%90%E3%81%99%E3%82%8B.html)
## 所感
- 現在、人に見せる前提で整理されていないので、整理したほうがいいなと思った。
- 言語の仕様を把握する為に作ったサンプルと、本腰入れて作ったものは分けて管理したい。
- 過去に、**LearningRecord**という形で、GitHubに上げていたので、この日記も載せてもいいかなと思った。  
&rarr;ただ、READMEをつけたりする必要があるので、あまり気が進まない。
## 明日の予定
- 今日で完全に整理が終わらなかったので、明日中に整理を終えたい。
Rinnaさんとおしゃべりアプリ

https://developers.rinna.co.jp

Rinna Developerで公開されてるAPIを試してみた。

https://learn.microsoft.com/ja-jp/azure/bot-service/bot-service-quickstart-create-bot?view=azure-bot-service-4.0&tabs=csharp%2Cvs

上のサイトを参考にチャットbotを作成します。

```bash
dotnet new echobot -n <your-bot-name>
```

作成したテンプレートの`EchoBot.cs`を下のように書き換えます。

```csharp
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
// Generated with EchoBot .NET Template version v4.17.1

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using Newtonsoft.Json.Linq;

namespace EchoBot.Bots
{
    public class EchoBot : ActivityHandler
    {
        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {

            var content = new StringContent("{ \"rawInput\":\"" + turnContext.Activity.Text + "\", \"outputLength\": 25 }");

            var client = new HttpClient();


            // Request headers

            client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache");

            client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "******");
            var uri = "https://api.rinna.co.jp/models/cce";


            HttpResponseMessage response;

            // Request body

            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            response = await client.PostAsync(uri, content);
            Console.Write(response);
            JObject json = JObject.Parse(response.Content.ReadAsStringAsync().Result);
            var replyText = $"Echo: {json["answer"]}";
            await turnContext.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);

        }
    }
}
```

https://learn.microsoft.com/en-us/azure/bot-service/bot-service-debug-emulator?view=azure-bot-service-4.0&tabs=csharp

Bot Emulatorを使うと簡単にテストできる。

![スクリーンショット 2022-10-30 22.19.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235110/87c01aa5-3624-9044-2830-5f2a6dc3db43.png)
フロントエンド開発で使う便利なツールまとめ(随時更新)

フロントエンド開発を担当しています、あやかです。

社内のフロントエンドで開発する際に使用する便利ツールを教えてもらい、ちょこちょこと便利ツールがたまってきたので、ここでわかりやすくまとめるか〜と思い、一覧を作成しました。

皆様の開発のお役に立てると嬉しいです！ではどうぞ🙌

## 便利アプリ
■LGTMの画像生成してくれるツール
[LGTMoon - 最もシンプルなLGTM画像ジェネレーター ](https://lgtmoon.herokuapp.com/)

■コードの差分表示ツール
[Mergely - Diff online, merge documents](https://editor.mergely.com/)

■HTMLメール版のCan i use
[Can I email… ](https://www.caniemail.com/)

■正規表現チェッカー
[Debuggex: Online visual regex tester. JavaScript, Python, and PCRE. ](https://www.debuggex.com/)


## Chrome拡張機能
■Metaタグ見れる拡張機能
[SEO META in 1 CLICK](https://chrome.google.com/webstore/detail/seo-meta-in-1-click/bjogjfinolnhfhkbipphpdlldadpnmhc?hl=ja)

■JSONを綺麗に見れる拡張機能
[JSON Viewer](https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh?hl=ja)

■文字をカーソルで選択するとDeepLをその場で使える拡張機能
[DeepL翻訳：読みながら、書きながら使える翻訳ツール](https://chrome.google.com/webstore/detail/deepl-translate-reading-w/cofdbpoegempjloogbagkncekinflcnj?hl=ja)

■Vue.jsのデバック拡張機能
[Vue.js devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=ja)

■Webサイトのパフォーマンスを測定する拡張機能
[Lighthouse](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=ja)


## パフォーマンス
■最近Chromeに追加されたperformance insightsタブ
[Performance insights: Get actionable insights on your website's performance - Chrome Developers](https://developer.chrome.com/docs/devtools/performance-insights/)
Google Apps Script(GAS)でメールアドレスの一覧を取得と書き込みメモ



よくある処理なのでメモ

こんな感じのシートがあってメールのA:A列をまるっと抜き出したいという処理です。

> ![スクリーンショット 2022-10-30 22.02.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/05235695-74c1-eed6-f3a1-080bca15fb8a.png "スクリーンショット 2022-10-30 22.02.11.png")

## 取得

- 余計な空行も入ってくるのでfilterで削除
- 配列が入れ子構造になるのでflat()で入れ子構造を無くします。

```js
function getEmailList() {
  const SSID = `<スプレッドのID>`;
  const sheet = SpreadsheetApp.openById(SSID);
  const range = sheet.getRange(`シート1!A:A`);
  const values = range.getValues();
  values.shift(); //ヘッダー部分、先頭削除
  const emailList = values
                      .filter(email => email[0]) //中身のある要素抽出
                      .flat(); //入れ子構造削除
  console.log(emailList);
}

```

- 結果

```
['aaa@gmail.com'
'bbb@gmail.com'
'ccc@yahoo.co.jp']
```

こんな感じでメールアドレスのみの配列で取得できました。

## 書き込み

書き込みは至ってシンプル。1番左の列だけならこれでOK

```js
function addEmailList(email = 'hoge@hoge.com'){
  const SSID = `<スプレッドのID>`;
  const sheet = SpreadsheetApp.openById(SSID);

  sheet.appendRow([email]);
}
```
WSL2を使って、Windows上でUbuntuを使用する方法


◆WSL2とは・・？
⇒マイクロソフト社によって提供されているサブシステムで「Windows Subsystem for Linux」の略のことです。機能としてはWindows上でLinuxを動作させるための実行環境を作成できる機能です。


◆利用することで何ができるのか？

・手元のWindows OSをこれまで同様に使いながら、同じWindows上でLinuxを動作させることが可能
⇒Windowsのインストールされているソフトウェアのような環境で利用可能することができる

・WSL1との違いとしてハイパーバイザーの上にカーネルがあるため、完全なLinuxとしての使用が可能となっている点


◆目的

インストールすることで現在契約しているVPSに接続するため


◆実際にインストール設定

①まずWindowsOSのバージョン確認
Windowsキー + Rを押下して、「winver」を入力
下記画面が出力されているため、バージョンを確認を行う
![2022-10-30 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2922312/a6c49ca9-5eae-c1ee-3f6f-c992bf04a4d6.png)


②PowerShellからインストール実施
Windows PowerShell > Windows PowerShell の項目上で右クリックし、「管理者として実行する」

※無印のPowerShellを押下すること

管理者権限で開くことができましたら、続いて下記コマンドを実行
```
PS C:\WINDOWS\system32> wsl --install
```


![2022-10-30 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2922312/55c20275-81f5-31dd-03d7-427681e340fc.png)

エラー発生がありましたが、正常にインストールはされているみたいなので無視して進めていきます。
「コンポーネント: 'Ubuntu' エラーコード:  0x80072eff 要求された操作は正常に終了しました。」

すべてのインストールが完了しましたら、PCを再起動

③再起動後、Ubuntuを操作

再起動後、プロンプトが開き、Ubuntuのインストールがはじまります。
![2022-10-30 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2922312/379cca46-76cd-f1ab-44f0-48f5aec732a3.png)

このままインストールを待ち、Ubuntu上でユーザー名とパスワードを入力いたします。

```
PS C:\> wsl --list --verbose
  NAME      STATE           VERSION
* Ubuntu    Running         2
PS C:\>
```

起動確認しましたら、インストールは終了になります。
Pythonでフォルダ内すべての画像の回転をしてみた

## 目的
画像の回転だけであれば調べればすぐ出てきたのですが、フォルダ内すべての画像を
回転の対象にできないかと思い色々調べてまとめてみました。

## ソースコード
下記のソースコードは、ファイル内にあるすべての画像を読み込んで
その画像を反時計回り一回行い、再度保存するプログラムです。
```Python
import numpy as np
import cv2
import os,glob,random


save_dir="./hogehoge"  
files=glob.glob("./hugehuge./*.JPG")
n=0
for l in files:
    img=cv2.imread(l)
    outfile=save_dir+"/"+str(n)+".jpg"
    #　反時計回りに回転させる
    img=cv2.rotate(img , cv2.ROTATE_90_COUNTERCLOCKWISE)
    cv2.imwrite(outfile, img)
    n+=1
```
## 解説
保存先のディレクトリを指定します。
この場合、ソースコードと同じディレクトリ配下のhogehogeというフォルダに保存するようになっています。

```Python
save_dir="./hogehoge" 
```
 
ソースコードと同じディレクトリ配下のhugehugeというフォルダの中の任意のファイル名の画像をfilesで定義します。
<font color="blue">\*はワイルドカードになっており、任意の文字列を指します。</font>
例えば、\*の箇所を特定のファイル名(1.jpgという画像など)にすれば、その画像だけを回転させます。
<font color="red">なので、このコードを実行する際はhugehugeフォルダ内のすべての画像が回転してしまうので注意してください。</font>

```Python
files=glob.glob("./hugehuge./*.JPG")
```

Pythonの強みであるfilesで定義した任意の数のファイルをそれぞれlとしてfor文をまわします。
```Python
for l in files:
```

openCVのimreadを使い画像の読み込みです。
 
```Python
img=cv2.imread(l)
```

保存先のディレクトリを指定します。
先ほどもsave_dirで保存先のフォルダを定義しましたが、画像のファイル名は定義していないので、
今回はn=0からの連番で画像のファイル名を指定します。
なので、回転されて保存された画像のファイル名は0.jpg~n.jpgとなるわけです。
nの最大値は読み取り元のhugehugeフォルダ内の画像の枚数に依存します。

```Python
outfile=save_dir+"/"+str(n)+".jpg"
```

本題の画像の回転ですが、今回はopenCVのrotateを用います。
第1引数に画像、第2引数に回転の方法を指定します。
今回は反時計回りを指定しますので、cv2.ROTATE_90_COUNTERCLOCKWISEを用います。
```Python 
# 反時計回りに回転させる
img=cv2.rotate(img , cv2.ROTATE_90_COUNTERCLOCKWISE)
```

時計周りの場合は第2引数に以下を用います。
```Python
cv2.ROTATE_90_CLOCKWISE
```
180度回転の場合は第2引数に以下を用います。
```Python
cv2.ROTATE_180
```
最後に画像の保存をopenCVのimwriteを用いて行います。

```Python
cv2.imwrite(outfile, img)
```
以上で解説はおしまいです。
お疲れ様でした！

参考文献
[引用元](https://note.nkmk.me/python-pillow-rotate/)
App Store Connectのリジェクト　UIBackground

リリースしたiOSアプリの更新を行い審査を上げていたが
リジェクトされて返ってきた。
理由は下記。

Guideline 2.5.4 - Performance - Software Requirements

Your app declares support for audio in the UIBackgroundModes key in your Info.plist, but we were unable to play any audible content when the app was running in the background.

どうやら、xcodeでこのチェックが入っていることが影響しているらしい。
アプリがbackground musicを使用していない場合はチェックを外してビルドする。

![Screen Shot 2022-10-30 at 21.38.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2436967/b4cc4ae2-6fb9-ff56-16de-e7fb83e0d751.png)
Laravel アプリケーションをHerokuにデプロイしてみた

# Laravel Documents

https://devcenter.heroku.com/articles/getting-started-with-laravel


https://chigusa-web.com/blog/heroku-laravel/


# 環境設定
>・php -v　 PHP 8.1.6
・composer -V 　Composer version 2.4.2
・git 0-version 　git version 2.37.1.windows.1

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/81f4b8b0-b054-59d1-3c6b-5cd67c9e4713.png)



# Creating a Laravel application

```terminal:terminal
    laravel new hello_laravel_heroku

    cd hello_laravel_heroku
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/b453eec1-ed35-65c0-b102-ccf1d4859f66.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/d938f428-edcd-8e46-7ac5-fd8713217d14.png)

# Initializing a Git repository
```terminal:terminal
    git init
    git add .
    git commit -m "new laravel project"
```

# Deploying to Heroku


### Creating a Procfile

```terminal:terminal
    echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile
    git add .
    git commit -m "Procfile for Heroku"
```

### Creating a new application on Heroku
```terminal:terminal
    heroku create
```
### Setting a Laravel encryption key
```terminal:terminal
    php artisan key:generate --show
    base64:(コード)
    heroku config:set APP_KEY=base64:(コード)
```
### Pushing to Heroku
```terminal:terminal
    git push heroku master
    heroku open
```

# Complete Deploy:confetti_ball:

https://obscure-tundra-18776.herokuapp.com/


#Best Practices

### Changing the log destination for production
```terminal:terminal
    
```

# DBの設定

https://devcenter.heroku.com/articles/cleardb


```terminal:terminal
    heroku addons:create cleardb:ignite
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/0752874b-3677-6f33-37fe-f312efa4c21f.png)

```terminal:terminal
    // windows
    heroku config | findstr CLEARDB_DATABASE_URL
    mysql://(コード)

    heroku config:set DATABASE_URL='mysql://(コード)'

    heroku config:set DB_CONNECTION=mysql
```
非同期処理でクラッシュした時の対処

# はじめに
今回は非同期処理であるコルーチンを使用した際、遭遇したクラッシュの対処法を調べてもなかなかいいものが見つからず苦労したので、
同じエラーが出た際にすぐに対応できるようにやった内容を記事に残しておきます。

# 今回発生したエラー
logがこちら
```
The exception was not handled due to missing onError handler in the subscribe()
method call. Further reading: https://github.com/ReactiveX/RxJava/wiki/Error-Handling |
java.lang.IllegalStateException: Method setCurrentState must be called on the main thread
```

訳
subscribe() メソッド呼び出しに onError ハンドラがないため、例外は処理されませんでした。さらに読む: https: //github.com/ReactiveX/RxJava/wiki/Error-Handling | java.lang.IllegalStateException: メソッド setCurrentState は**メイン スレッドで呼び出す必要があります**


実際のコードがこちら
```
 viewModel.変数.subscribe {
            if (it) {
            // 画面遷移を促すメソッド
                }
```

# 今回のエラー回避方法

```
 viewModel.変数.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
　　　　　　　if (it) {
            // 画面遷移を促すメソッド
                }
```

# 内容
非同期処理内でUIの操作やUIに変化を与える処理を加えるとクラッシュします
非同期処理でUIを操作　または　UIに変化を加えたい場合は、エラー内容にもある通り
処理を**メイン スレッドで呼び出す必要があります**

具体的には　observeOn() を追加することで、購読後の処理するスレッド
を追加しました

# おわりに
今回はRxjavaでの非同期処理で遭遇したクラッシュに対しての対応でした
非同期処理内ではUIに対してのアクションは行えないのだと、強く認識することになりました
今後のkotlinではcoroutinesを使用することが増えると思いますが、
coroutinesでも同じことが言えると思いますので、非同期処理の勉強がまだまだ必要だなと実感すると共に
注意が必要だなと思いました

今回の対応は私の遭遇した問題に対しての対処になります
同じようなエラーで困っている方がいましたら、参考程度に役に立てていただければ幸いです

# 参考
https://qiita.com/hatt0519/items/c8875f822b752a188956

https://www.kimullaa.com/posts/201806231026/

https://beanidealisticrealist.hatenablog.com/entry/2019/09/23/222023
AWS CDKを何ヶ月か使ってみたのでその使い勝手をレポートします

# これはなんですか

AWS CDKを３〜４ヶ月使ってみての事実と感想を列記します。

## 私のスペック
オールラウンダーなアーキテクト。
インフラ専業ではないけど最近修行してインフラスキルをあげている、AWSで一通りのものを構築、運用して基本的なことは多分わかってるんじゃないかなと思われる。

## AWS CDKとは

諸々の言語でAWSのインフラを記述できるさいきょおのIaC。

## で、何したの？
* VPC, SubnetなどのVPC世界での取り回し方を理解
* CloudFrontおよびS3、Route53の構築
* ALB, ECS, SQSの構築とか設定
* ECS, Code BuildなどのCI/CD
* 上記一切合切のインフラ作ったり消したりを github actions と連携

## 結論

出来上がってしまえば涙でるほど便利です。
しかし、ほしいものをつくるのにべらぼうな時間がかかります。

サンプルのレポジトリにテンプレとして載ってるものでよいのであれば、割と簡単に作れますが、ちょっとしたカスタマイズをしようとした瞬間その文献の少なさ、作って壊しての検証時間の多さに驚愕します。

特に地獄みあったのは ECSとCodeBuild。
task定義をつるしで作るとか、全くといっていいほど文献のないCodeBuildでクッソ時間とられて地獄みありました。

他にあったことを以下に徒然と書いておきます。

* S3やECRに何か残ってると消してくれないし、なぜか`cdk destroy`してもECRのレポジトリが消えない。
* 上記をはじめとしたちょまちょまと隙間があり全てを完結できない（体感９６％サポートな感触）
* なのでAWS CLIなどで補完しながらやる必要がある
* ベースとなっているCloudFormationの制約がそのまま制約としてある、例えばCode Deploy作れませんとか
* 実行してみるまでそのコードがあっているのかわからない
* インフラの構築、削除（破壊？）に時間がかかる、これはインフラとしてのサガなので仕方ないけれど、反復すると時間が飛びます
* AWS何も知らない状態でアタックするのは構築後の正解がみえず迷走しまくるのでマジでやめたほうがいい、最低でもどのサービスをどのようにして構築するのか、仕組みを理解してから入るべき

もともとインフラがPoCなどに時間をとられるものなので、あまり深く考えていませんでしたが、思った以上に時間がべらぼうにかかることを把握しておらず、お客さんに迷惑かけちゃったかなと反省していますorz
そんな中、生暖かく見守ってくれたお客様に感謝です。

１回作ったところは即再利用して構築できるので、書いたコードは財産だと思います。

この先はかすれていて読めない。
Kotlinのfor文

<h2>for文の書き方</h2>

Kotlinでのfor文は下記のような構成である。

        for(変数 in A..Z) {
            　// 処理
        }

A..Zの部分には、『0..26』のように、ループさせたい回数を記載する。
変数には最初ののループ時に指定した範囲の最小の値が格納されている。ループ処理が実行されるたびにインクリメントする。

        //Java
        for(int i = 0 ; i<=5; i++){
            System.out.println(i + "回目");
        }

        //Kotlin
        for (i in 0..5) {
            println(i.toString() + "回目")
        }

    // 実行結果
    0回目 
    1回目
    2回目
    3回目
    4回目
    5回目

「..」の部分には、「step」や「downTo」、「until」を記載が可能である。

<h3>step</h3>
任意の数ずつ変数の値を増やしたい場合に使用する。

        for(変数 in A..Z step 値) {
            　// 処理
        }

範囲指定した後に「step 値」を記載することで、記載した数ずつ値が増加していく。
実際に記載すると下記となる。

        for(i in 0..5 step 2) {
            println(i.toString() + "回目")
        }

    // 実行結果
    0回目
    2回目
    4回目

0から始まり、0+2、2+2と iの値が5になるまで繰り替えしている。

<h3>downTo</h3>
変数の値をデクリメントさせる場合に使用する。

        for(i in A downTo Z) {
            // 処理
        }
「..」を記載していたが、この部分が「downTo」となる。
実際に記載すると下記となる。

        for(i in 5 downTo 0) {
            println(i.toString() + "回目")
        }

     // 実行結果
     5回目
     4回目
     3回目
     2回目
     1回目
     0回目

5から始まり、1ずつ数を減らしていく。
2ずつ減らしたい場合等は、上記で記載した「step」と組み合わせる。

        for(i in 5 downTo 0 step 2) {
            println(i.toString() + "回目")
        }

    // 実行結果
    5回目
    3回目
    1回目

<h3>until</h3>
範囲の最後の値を含めない場合に使用する。

        for(変数 in A until Z) {
            // 処理
        }

「..」を記載していたが、この部分が「until」となる。
実際に記載すると下記となる。

        for (i in 0 until 5) {
            println(i.toString() + "回目")
        }

     // 実行結果
     0回目
     1回目
     2回目
     3回目
     4回目


untilを使用せず、0..4でも同じ結果が取得できる。
【Ruby】rbenvで管理しているRubyのバージョンを変更したいとき


# 概要
Rubyのバージョンをrbenvで管理しているが、プロジェクトによってRubyのバージョンが違うため、切り替え方をメモする。

# 実行環境
* MacOS Monterey バージョン12.6

# 手順
* rbenvのバージョンを確認
```
$ rbenv --version
rbenv 1.1.2
```

* rbenvでインストール可能なrubyのバージョンを確認
```
$ rbenv install --list-all
1.8.5-p52
1.8.5-p113
1.8.5-p114
1.8.5-p115
1.8.5-p231
1.8.6
1.8.6-p36
1.8.6-p110
1.8.6-p111
1.8.6-p114
1.8.6-p230
1.8.6-p286
1.8.6-p287
1.8.6-p368
1.8.6-p369
・
・
・
（以下、省略）
```

* 特定のrubyのバージョンをインストール
```
$ rbenv install 2.6.5
```

* rbenvの設定バージョンを確認
```
$ rbenv versions
  system
  2.2.1
  2.3.0
  2.3.5
  2.5.0
  2.5.1
* 2.6.5 (set by /Users/owner/.ruby-version)
```

* グローバルのRubyバージョンを設定する場合
```
$ rbenv global 2.5.0
```

* ローカルのRubyバージョンを設定する場合
```
$ rbenv local 2.5.0
```

# 参考資料
* rbenv
https://github.com/rbenv/rbenv#installation
【シェルスクリプト】リトライ処理

## 回数上限あり

```zsh
MAX_RETRY=5
for i in {1..$MAX_RETRY}
do
  コマンド && break
done
```

## 回数上限なし

```zsh
COMMAND_STATUS=1
until [ $COMMAND_STATUS -eq 0 ]
do
  コマンド
  COMMAND_STATUS=$?
done
```
【WSL2 Ubuntu22.04】 Elixir DesktopをWSLgで動かしてみる（完成版）

# 課題
WSLgが有効になっていれば、Ubuntuの場合と同様の方法でElixir Desktop動作するのではないか？

[Elixir Desktopのサンプル](https://github.com/elixir-desktop/desktop-example-app)を実行してみました。

ウインドウは表示されて、動きそうなんですが、ウインドウ内にTodoアプリが表示されません。真っ白な表示でした。

# 解決策

次の環境変数を設定することで、動くようになります。
$ export GDK_BACKEND=x11

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/cfe07bc5-1ae8-7655-14f3-174b545c0d24.png)

Vega-LiteもWSLgで表示できるようになりました。

# 回避策発見の経緯


WSLgでは、Vega-liteの表示も画面が真っ白で表示されませんでした。
もしかして、Elixir desktopの問題ではなく、wxWebViewの動作がおかしいのでは？
Ubuntuの場合とwx関係のインストールされれているパッケージに違いはない。
wxWebView表示する.cppプログラムを作って動かしてみる

```
masa@wsl-elixir:~/wx$ ./hello
WaylandCompositor requires eglBindWaylandDisplayWL, eglUnbindWaylandDisplayWL and eglQueryWaylandBuffer.
Nested Wayland compositor could not initialize EGL
```
このようなエラーが発生し、表示されない。やはり、wxWebViewの問題。
エラーメッセージを検索した結果、[issue](https://github.com/microsoft/wslg/issues/595)に回避策を発見



# dbusに関するエラーの対応

この対応は実施しなくても動作します。エラー表示をでなくした場合、systemdを有効することで、でなくできます。
WSL2のubuntuのデフォルトでは動作していないです。

バージョンが古いと対応していない。以下のバージョンはOKでした。

```
> wsl --version
WSL バージョン: 0.70.4.0
カーネル バージョン: 5.15.68.1
WSLg バージョン: 1.0.45
MSRDC バージョン: 1.2.3575
Direct3D バージョン: 1.606.4
DXCore バージョン: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windowsバージョン: 10.0.22621.675
```
wsl.confを修正し、wslをshutdownする。

```config:/etc/wsl.conf
[boot]
systemd=true
```



参考

https://devblogs.microsoft.com/commandline/systemd-support-is-now-available-in-wsl/
https://x410.dev/cookbook/wsl/sharing-dbus-among-wsl2-consoles/
https://github.com/microsoft/wslg/issues/595
ターミナルから「pstorm」コマンドでPhpStormが起動できない

### 背景
毎回PhpStormを開く→プロジェクト選択するの面倒だな、ターミナルから開けば楽じゃん、と調べると
ちゃんとPhpStormを起動する方法があるじゃない。
コマンドは以下
```
$ pstorm .
```

結果は、、、、ダメ。。
```
zsh: command not found: pstorm
```

whichコマンドで確認すると確かにない
```
pstorm not found
```
### 対応
1. PhpStorm > ツール > コマンドラインランチャーの作成を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360742/d88a702f-7fd5-48fc-9aac-8dba0ba05730.png)

2. デフォルトで`/usr/local/bin/pstorm`になっているのでそのままOKを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360742/a91518e8-bcbb-d481-d2c9-02e5b67c5a2c.png)

### 結果
```
$ pstorm .
```
無事プロジェクトを開けるようになりました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360742/91d58280-c60f-1f07-72e3-da5fdb1e351d.png)
Splunk: IPアドレスをCIDR表記で検索する


###### 実施環境： Splunk Free 8.2.2

### 0. 概要

 IP アドレスの表記で、以下のようなものを見たことがある人は多いと思います。

` 198.1.32.0/28 `

細かい説明は省きますが、これは CIDR (サイダー)表記といい、 IP アドレスの範囲を記述する表記法の1種です。
 Splunk の検索では、この CIDR 表記での条件指定も使用できます。

### 1. search コマンドの場合

 search コマンドでは、特別なオプションなどなしに CIDR 表記での検索が可能です。
 CIDR 表記を記載した文字列をイコール(=)で指定すれば、 CIDR 表記で検索できます。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval IPV4 = "10.20.30." . CNT
| search IPV4 = "10.20.30.4/30"
```

![WS000346.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/26d920e6-8875-b66c-6a91-1aa72f9562ea.jpeg "search_ipv4")

 IPv4 アドレスだけでなく、 IPv6 アドレスにも対応しています。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval IPV6 = "2022::" . CNT
| search IPV6 = "2022::4/126"
```

![WS000348.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/70ea8191-d31e-4973-705c-becf999596f0.jpeg "search_ipv6")

この search コマンドは SPL 文の先頭で省略して使用されることがほとんどです。
無論、コマンドが省略されている場合でも CIDR 表記での検索は可能です。

```Splunk:Splunk
index="_internal" ip_address="127.0.0.0/24"
| table ip_address
```

![WS000350.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/f7a3b3d3-f8c8-abd7-8125-b8d3348c44fd.jpeg "search_ip")

### 2. where コマンドの場合

 eval コマンドや where コマンドでは、 cidrmatch という評価関数を使用することで CIDR 表記が扱えます。
引数は以下の通りです。

 cidrmatch( CIDR 表記の IP アドレス範囲, IP アドレス )

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval IPV4 = "10.20.30." . CNT
| where cidrmatch("10.20.30.4/30", IPV4)
```

![WS000347.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/0d585d4a-d1ac-e084-bdad-6da8478bcdd2.jpeg "where_ipv4")

こちらも IPv4 アドレスだけでなく、 IPv6 アドレスにも対応しています。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval IPV6 = "2020::" . CNT
| where cidrmatch("2020::1/127", IPV6)
```

![WS000349.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/16e5abb9-0658-363f-ea5f-a3c29f89d589.jpeg "where_ipv6")
[Python] listを逆順にソート かつ　0除去する

## 目的
数値の配列listから下記を行う。
- 0除去
- 逆順にソート

## コード
```Python
testListExcluded = list()
testList = [0,1,0,2,0,0,3]
print(testList)

# 逆順にする
# reverse()が返すのはNoneなので注意。
testList.reverse()
print(testList)

# 0除去する
for value in testList:
    if value != 0:
        testListExcluded.append(value)
        
print(testListExcluded)
```

## 出力結果
[0, 1, 0, 2, 0, 0, 3]
[3, 0, 0, 2, 0, 1, 0]
[3, 2, 1]
【備忘録】Win10での32bitアプリケーションのレジストリ登録でリダイレクトによる沼にはまった話

# はじめに
私が今働いている会社も32bitアプリケーションがWindows10やWindows7で運用されていたりします。
Windows10は64bit OS、Windows7以前は32bit OSで動いています。
今回のアプリケーションは、パッケージで環境に展開するのですが、その際**バッチファイル**でレジストリ登録処理をする箇所があります。
この記事では、32bitアプリケーションがバッチファイルでレジストリ登録する際になぜか登録ができなかった原因、そしてどう解決したのか備忘録として書いていこうと思います。

# アプリケーションのバッチファイルによるレジストリ登録で困った問題点
そもそも期待された動きとして、32bit OSと64bit OSでレジストリ登録したいキー値がことなるようにしたかったのです。

これはあくまで例なのですが、以下のように登録したかったのです。

```
32bit OS
HKLM\SOFTWARE\Key
Key=1

64bit OS
HKLM\SOFTWARE\WOW6432Node\Key
Key=1
```
64bit OSで32bitアプリケーションを動かす際、リダイレクトと呼ばれるOSの機能によって登録されるキーの場所が異なります。(レジストリのリダイレクトについては[こちら](https://learn.microsoft.com/ja-jp/windows/win32/winprog64/registry-redirector)から)

今回はOSによってレジストリキーの登録先が変わります。なので、OSによってバッチファイルが登録先を変更できるように実行したかったのです。

## OSのbit数をコマンドプロンプトで判断する方法
そもそもOSが32bitか64bitかを判断する場合はコマンドプロンプトで```%PROCESSOR_ARCHITECTURE%```を入力することで判断できます。  

```bat
> %PROCESSOR_ARCHITECTURE
```

bit数に応じて、以下の結果が返ってきます。
|OS|返送結果|
|-|-|
|32bit|x86|
|64bit|AMD64|

そのため、バッチファイルでOSで処理を分岐させたい場合は、次のように書けばできます。

```
if %PROCESSOR_ARCHITECTURE% equ "x86" (
// 32bit OSで実行したいコマンドを記載する。
) else (
// 64bit OSで実行したいコマンドを記載する。
)
```


## なぜ64bit OSでバッチファイルによるレジストリ登録できなかった?
コマンドプロンプトの実行ファイル名はcmd.exeです。
実は64bitOSで32bitアプリケーションがバッチファイルを実行する時、cmd.exeは64bitではなく32bitで動きます。
cmd.exeは32bitと64bitで実行ファイルが異なります。

32bitアプリケーションがバッチファイルを実行する場所
| 実行OS | ファイルパス |
|-|-|
|32bit|c:\windows\Syswow6432\cmd.exe|
|64bit|c:\windows\System32\cmd.exe|

このように同じcmd.exeでも32bitか64bitかで実行場所が異なるため、バッチファイルがjっ甲できても上手く分岐ができませんでした。

# どう対処した?
結論から言うと、```%PROCESSOR_ARCHITEW6432%```で解決できました。
このコマンドは返却結果が、```%PROCESSOR_ARCHITECTURE%```と違います。

|OS|返却結果|
|-|-|
|32bit|not found|
|64bit|AMD64|

なので、バッチファイルで分岐する場合は次のようにすれば大丈夫です。

```
if "%PROCESSOR_ARCHITEW6432%" equ "AMD64" (
// Win10で実行したいコマンドを記載する。
) else (
// 32bit OSで実行したいコマンドを記載する。
)
```

Windows10で32bitアプリケーションのバッチファイルによるレジストリ登録が正常にできるようになりました。
これでリダイレクトの問題も解決です。

# 最後に
プログラミングの問題ならエラーやログを見れば解決できそうでしたが、コマンドプロンプトの実行exeの問題だったとは思わなかったので思わぬ沼にはまって1日消化してしまいました。
新たな知識が得られたと前向きに捉えて、開発業務をしたいと思います。


### PS
Twitterやってます。
https://twitter.com/koji1122wiki
エンジニアとして色々発信しているのでよかったらフォローお願いします。
また質問などはこの記事のコメントからでもツイッターのDMでも大丈夫です。

それでは長々と見てくださり有難うございました！

# 参考文献
https://ss64.com/nt/syntax-64bit.html
https://wa3.i-3-i.info/word14254.html
paiza.ioでelixir その32

# 概要
paiza.ioでelixirやってみた。
URI使ってみた。

# サンプルコード

```

URI.decode("https%3A%2F%2Felixir-lang.org")
|> IO.inspect
URI.decode_query("foo=1&bar=2")
|> IO.inspect
URI.encode("ftp://s-ite.tld/?value=put it+й")
|> IO.inspect
URI.encode("a string", &(&1 != ?i))
|> IO.inspect
query = %{"foo" => 1, "bar" => 2}
URI.encode_query(query)
|> IO.inspect
URI.merge(URI.parse("http://google.com"), "/query") 
|> to_string()
|> IO.inspect
URI.parse("https://elixir-lang.org/")
|> IO.inspect
URI.query_decoder("foo=1&bar=2") 
|> Enum.to_list()
|> IO.inspect
uri = URI.parse("http://google.com")
URI.to_string(uri)
|> IO.inspect


```

# 実行結果


```
"https://elixir-lang.org"
%{"bar" => "2", "foo" => "1"}
"ftp://s-ite.tld/?value=put%20it+%D0%B9"
"a str%69ng"
"bar=2&foo=1"
"http://google.com/query"
%URI{
  authority: "elixir-lang.org",
  fragment: nil,
  host: "elixir-lang.org",
  path: "/",
  port: 443,
  query: nil,
  scheme: "https",
  userinfo: nil
}
[{"foo", "1"}, {"bar", "2"}]
"http://google.com"
```

# 成果物

https://paiza.io/projects/77BzOOzr83t32d_meONFSA

以上。
AzureでかんたんにIoT #01 - IoTハブを作成する

## はじめに
本記事では、AzureでIoTデバイスとの連携を実現するためのサービスであるIoTハブのサービス作成方法について解説します。

IoTハブは、Azureが提供するIoTソリューションの中の一つになります。
何ができるサービスかと言うと、かんたんに言えばエッジデバイスとクラウドをつないでデータを双方向へやりとりするサービスになります。

IoTに詳しい人、「それってMQTTブローカー？」と思った方もいらっしゃるかもしれません。
実はAzureはもともとIoTではAMQPをメインに通信プロトコルとして採用していたので、MQTTに対応に関しては実は少し後発です。
現在はMQTTをサポートしていますが、一般的なMQTTブローカーの全ての機能を網羅しているわけではなさそうです。

## AzureでIoTハブを探す
まず、Azure Portalへログインしましょう。
Azure Portalからリソース作成でIoTハブを見つけて作成するでも良いですが、検索窓で `IoT` で検索するとかんたんに見つかります。（英語ではIoT Hub）
検索結果のサービスの中からIoT Hubを選択しましょう。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81226/d6cd088c-9d26-2d36-0a25-021ca1dd43f6.png)

はじめてこのサービスへアクセスした場合、まだ何もIoTハブが作成されていないので、「表示するIoTハブがありません」と表示されます。 **IoTハブの作成** ボタンをクリックします。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81226/e9ea09d3-5c01-65a5-931c-d0cb49a93aa8.png)

## IoTハブを作成する
IoTハブの作成画面では、最初に **基本** タブが選択された状態になります。
こちらで、 **サブスクリプション** を選択します。ここでは **PAYG(Pay-As-You-Go)** サブスクリプションを選択していますが、お持ちのサブスクリプションがあれば任意のものを選択してください。

**リソースグループ** は、ここでは新規作成で **dev** というのを作りました。すでにリソースグループを作成済みの場合はそちらから選択でもOKです。

**IoT Hub名** はこの世界中で重複しないユニークな名称を付与してください。ここでは **taiponrock-ioyhub** という名称にしました。

**領域** はデータセンターのリージョンですので、任意の場所を選択してください。当然近いDCの方が原則レイテンシが低くなります。ここでは (近くないのですが) **East US** を選択しました。

![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81226/8e244b90-66b7-d4c5-6480-d6a131d970c6.png)

次に **管理** タブを選択します。
**価格とスケールティア** はテストレベルであれば無料で利用できる **F1: Free レベル** を選択しましょう。自分の用途で有料プランを選ぶ必要がある場合はそちらでも構いませんが、従量課金が発生しますのでご注意ください。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81226/56e4b2aa-e8a3-1bb8-a924-6c5798bddc1b.png)

**確認および作成** タブへ進みます。
選択、または設定した内容に問題がないか確認した上で **作成** ボタンをクリックしましょう。
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81226/273a2a84-0835-ba11-32f0-8cbe731916bf.png)

これで作成の手続きは完了です。

## デプロイ
IoTハブのデプロイ画面へ遷移し、デプロイが実行されます。
デプロイ完了までしばらく(数分)かかりますので、焦らず待ちましょう。
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81226/fb78b2e3-b6df-6825-de3a-f59137cdcd63.png)

デプロイが完了すると、画面に「デプロイが完了しました」とメッセージが表示されます。
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81226/a2058c16-e167-5b0e-0691-20185bf0f459.png)

## 準備完了
これでIoTハブを利用する準備が整いました。
実際にデバイスと連携するためにはCA証明書の作成やデバイス登録が必要になります。このあたりは [AzureでかんたんにIoT #02 - IoTハブにデバイスを追加する](https://qiita.com/taiponrock/items/82d14fbe07d4e7017215) で解説してますのでそちらをご覧ください。

![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81226/51227375-f159-83a9-a652-b4287cf6f79c.png)

## 参考サイト
https://learn.microsoft.com/ja-jp/azure/iot-hub/
Google UXデザイン：ゴールステートメントを作成する

# はじめに

わたしが[Google UX Design Certificateで得られた素晴らしい体験][google]を、特に重要だと思われるポイントを小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ Google UX Design Certificateを受講してみてください。

[google]: https://qiita.com/mapami/items/7a0d0a3d4661c50f8bec

https://www.coursera.org/professional-certificates/google-ux-design

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/c3d622bb-c1ed-447b-c15e-c1bccff32a4a.png" width="800">

# ゴールステートメントとは

共感マップ、ペルソナ、ユーザーストーリー、ユーザージャーニーマップからの洞察を統合して、デザインの焦点となる範囲を考えましょう。それには、プロダクトゴールステートメントを作成します。

プロダクトゴールステートメントは、”プロダクトとそのユーザーにとっての利点を説明する1～2文”　です。

つまり、

***<font color="MediumVioletRed">『デザインの理想的なソリューションが示されている』</font>***　


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/7ed4ae1e-4190-89c6-2035-e84507a575d6.jpeg" width="500">

# ゴールステートメントの公式

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/0079e6f1-fdd5-1a3b-2d2a-b77ce0f3ac48.png" width="700">

- ***What***： 製品がユーザーに何をさせるのか？
- ***Who***: その行動が誰に影響を与えるのか？
- ***Why***: なぜその行動がユーザーにプラスの影響を与えるのか？
- ***How***: そして製品の効果をどのように測定するのか？

# プロブレムステートメントからゴールステートメントへ

### サンプル１
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/6cacd43f-1bfa-efe3-d0b6-b91452351a7e.png" width="700">

↓

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/30f1f8b8-a69b-144b-c7d0-3bd33faf6dca.png" width="700">

### サンプル2
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/1d11d0d8-0796-312e-aeea-471ab867ab2f.png" width="700">


# 強力なゴール・ステートメント

- ユーザーが取ることのできる具体的な行動、または製品が何をするのかを記述する。
- そのアクションが誰に影響を与えるかを定義します。
- その行動がもたらすポジティブな影響、または製品がユーザーのニーズを解決する理由を述べる。
- 測定可能な用語で成功を概説します。

:::note info
プロブレムステートメントなしでも、ゴールステートメントを作成できる：
- ペルソナによって、「誰が」を見つける
- ユーザーストーリーによって、「何を」を見つける
- 共感マップとユーザージャーニーマップによって、「なぜ」を見つける
:::
Crostiniを日本語で使えるようにするぞ！

# この記事の内容
　Crostiniを日本語で快適に使えるように設定することをまとめました。

# Crostiniとは
　CrostiniとはChrome OS上でLinuxを仮想環境として利用するためのシステムのことです。
　非公式ですが、標準の「Debian」以外のOSも利用できたはずです。

# 日本語化の設定を行う
1\. 言語の設定をする
2\. 日本語フォントを導入する
3\. 日本語入力ができるようにする

## 1\. 言語の設定をする
　初期状態の英語表示から日本語表示に変更します。
　次のコマンドでパッケージのアップデートをします。
~~~
sudo apt -y update&&sudo apt -y upgrade&&sudo apt -y autoremove
~~~
　次のコマンドで設定画面を開きます。
~~~
sudo dpkg-reconfigure locales
~~~
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2942430/08843020-bbbc-1cad-1527-777f21f9771e.png)
　「en_US.UTF-8 UTF-8」の項目にに入っているマークを外し、「ja_JP.UTF-8 UTF-8」の項目にマークを入れます。 そして、「Ok」を選択します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2942430/53ed71e4-14fa-76ff-757c-587989ef4557.png)
　「ja_JP.UTF-8」を選択して「Ok」で終了します。
　タスクバーのターミナルのアイコンを右クリックし、「Linuxをシャットダウン」でコンテナをシャットダウンさせます。 もう一度起動させるとターミナルの表記が日本語になるはずです。

## 2\. 日本語フォントを導入する
　何もしなくても初めから日本語表示はしてくれます。しかし、それでは見にくいことがあるので、見やすいフォントに変更します。
　次のコマンドでディレクトリを作成し、その中にフォントのファイルを保存します。
~~~
mkdir ~/.fonts
~~~
　「ファイル」のアプリで右上の三点リーダーから「非表示のファイルを表示」を有効にします。
　使用したいフォントのファイルを「.fonts」ディレクトリの中に保存すると、GUIアプリで表示されるフォントが変わるはずです。

## 3\. 日本語入力ができるようにする
　初期状態では日本語入力ができないため、日本語入力システムをインストールします。
　次のコマンドで入力メソッドの「fcitx」と日本語変換エンジンの「mozc」をインストールします。
~~~
sudo apt -y install fcitx-mozc
~~~
　このままでは日本語入力ができないので、環境変数というものを設定します。
　エディタで「/etc/environment.d/fcitx.conf」を開き、次の環境変数を追加します。
~~~
GTK_IM_MODULE=fcitx
QT_IM_MODULE=fcitx
XMODIFIERS=@im=fcitx
GDK_BACKEND=x11
~~~
　Fcitxの自動起動の設定ファイルを作成します。
　エディタで「~/.sommelierrc」を開き、次の内容を追加します。
~~~
/usr/bin/fcitx-autostart
~~~
 タスクバーのターミナルのアイコンを右クリックし、「Linuxをシャットダウン」でコンテナをシャットダウンさせます。 もう一度起動させて次の作業に進みます。
 Fcitxの設定をします。
 次のコマンドで設定画面を開きます。
~~~
fcitx-configtool
~~~
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2942430/a56b70e9-7704-6e79-05c2-28c4adc1f84a.png)
　左下の「＋」ボタンから「Mozc」を追加します。
　タスクバーのターミナルのアイコンを右クリックし、「Linuxをシャットダウン」でコンテナをシャットダウンさせます。 もう一度起動させると日本語入力ができるようになるはずです。

# 実際に確かめてみる
　実際に「gedit」をインストールしてGUIアプリで日本語入力ができるようになったのか確かめてみます。
　次のコマンドでエディタの「gedit」をインストールします。
~~~
sudo apt -y install gedit
~~~
　アプリケーション一覧から「gedit」を起動する。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2942430/6d6dfeae-01ac-bc98-b7c4-9f75769cd3d9.png)
　日本語入力ができるようになりました。
iOS16 (執筆時16.0.3) で、Canvas上でベジェ曲線で画像をマスクするとノイズが発生するときがあるよ。とりあえずノイズを出なくする方法を教えるよ。

:::note info
2023/1/23リリースのiOS16.3にて、以下のノイズは発生しなくなったようです。
変なノイズの問い合わせがあった場合は、「OSを最新に」と言い張りましょう。
:::

ベジェ曲線で画像をマスクしつつ、曲線をふわふわさせてオサレな雰囲気をだしたいときってありますよね。
**私はありました**

先日、このオサレな実装がiOS16では台無しになることに気づきました。
例：↓こんな感じでノイズ(謎の線)が描画されることがあります。

![noize.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6541/e0de2cfa-6eb1-89e4-b4c3-ce171aa592f1.png)

実際に動く(オサレではない)サンプルを用意しました。
bezierCurveToの曲線でclipした画像を描画する、ググると良く出てくる実装方法です。
下のcodepenをiOS16(iOS16.3以下)で実行するとノイズがチラチラと表示されると思います。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="zYjLZJq" data-user="393" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/393/pen/zYjLZJq">
  Noise appears on Canvas iOS16 </a> by 393 (<a href="https://codepen.io/393">@393</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


---

ノイズ発生の条件はざっと調べた範囲では以下のとおりです。

* clipしてdrawImageしたときに発生
* clipしてグラデーションでfillしたときにも発生
* 単色でfillのときには発生しない
* 2次ベジェ(quadraticCurveTo)、3次ベジェ(bezierCurveto)どちらの実装でも発生
* bezierのコントロールポイントが任意の座標のときに発生
    * 上のサンプルはアニメーションさせているので、ノイズがチラチラしていますが、任意の座標で止めるとノイズは表示されたままになります
    * ノイズでる座標の法則性はよくわからず

---

### 解決方法です。
上のcodepenにも実装してありますが、[toggle]ボタンを押すとiOS16でも、ノイズは発生しなくなります。
実装の違いはcodepenでjsを見てもらえばわかると思いますが、要はclipはしないで、patternで描画する、というのがポイントのようです。

この問題についてざっとググってみても、話題にしてる人も解決策も見当たらなかったので、ここに一つの解決策としてメモを残しておきます。
まだ見ぬ誰かのお役に立てれば幸いです。
SVGファイルをReactコンポーネントとして使う時の備忘録

# はじめに
- フロントエンド開発(React/TypeScript利用)で、簡単にSVGファイルを扱う方法のメモ。

# SVGファイルを用意する
- [Adobe Express](https://express.adobe.com/ja-JP/tools/convert-to-svg/#)がSVG変換で便利だった。

# SVGファイルをReactコンポーネントとして使う
- VSCodeなどでSVGファイルの中身を参照し、以下のようなファイルを作成する。
```TypeScript:Icon.tsx
export const Icon = (props: {
  width?: number | string;
  height?: number | string;
  style?: React.CSSProperties;
}) => {
  return (
    <svg
      xmlns="..."
      width={props.width}
      height={props.height}
      viewBox="..."
    >
      <path
        fill="..."
        opacity="..."
        d="..."
      />
      ...
    </svg>
  );
};
```
# 参考文献
- [How to Use SVG Icons in React App?](https://youtu.be/_bCQDa7wfRw)
【android】画面遷移について

## はじめに
画面遷移をしてみます。
また、遷移前のページで表示した値を遷移後の画面でも表示させてみようと思います。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689436/cd3c38ae-cf23-52b5-a13c-afbc1531b1ad.png)
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689436/3d5c53d5-a729-ed31-42fb-1453d172f3f4.png)



### java
```java:MainActivity.java
package com.example.testapp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView txt;
    private TextView nextTxt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txt = (TextView)this.findViewById(R.id.text1);
    }

    //ボタン（こんにちは）
    public void jHelloButton(View view){
        txt.setText(R.string.temp1);
    }

    //ボタン（HELLO）
    public void helloButton(View view){
        txt.setText(R.string.temp2);
    }

    //画面遷移ボタン
    public void nextButton(View view){
        setContentView(R.layout.next);
        nextTxt = (TextView)this.findViewById(R.id.next_text1);
        nextTxt.setText(txt.getText());

    }
}
```
```nextButton()```で次の画面（xml）をセットします。
```setContentView(R.layout.next);```で遷移するページをセットしています。
そのあとに、```nextTxt = (TextView)this.findViewById(R.id.next_text1);```で遷移先のxmlで定義している```next_text1```というテキストフィールドのプロパティを取得し、値をセットしています。

### xml
```xml:next.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/next_text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />

</LinearLayout>
```

## おわりに
Activityの切り替えで値を渡す方法は調べるとwiki等に載っていますが、レイアウトの切り替え時に値を渡す方法が見つからなかったので、試してみました。
詰まりポイントとしては、
```setContentView(R.layout.next);```で遷移する前に
```nextTxt = (TextView)this.findViewById(R.id.next_text1);```でテキストフィールドのプロパティを取得しようとしてもエラーになります。
おそらく、```this.findViewById```は遷移後のxmlを示しているようです。
そのため、遷移前に取得しようとすると「そんなID無いよ」と怒られているのだと思います。
定石としては、Activityで切り替えて、値を渡したほうが良いのでしょうね。
登録前の確認画面としては使えるのではないでしょうか。
PFCPのルールまとめてみた

# PFCPとは
3GPPの標準仕様(Technical Specification, TS)の一つで、Packet Forwarding Control Protocolのこと。4G LTEのコア設備である、SGW-CとSGW-U、PGW-CとPGW-U、5Gで言えばSMFとUPFで使われるプロトコル。
C-Plane側(SGW-C、PGW-C、SMF)がU-plane側(SGW-U、PGW-U、UPF)にパケットの転送等に関するルールを制御する。

# PFCPで使われるルール郡
| ルール | 名称 | 役割 |
|---|---|---|
| PDR |Packet Detection Rule|受信したパケットに対する判定条件およびパケットに適用するルール群を規定する|
|FAR|Fowarding Action Rule|パケットに付与するトンネリングヘッダ情報や使用するインタフェースなど転送にかかわる動作に加え、パケットの破棄もしくはバッファリングを行うなど転送要否を規定する|
|BAR|Buffering Action Rule|保持する最大パケット数やDownlinkパケット到着からSGW-C/SMFに対し通知するまでの滞留時間などバッファリングに関して規定する|
|QER|QoS Enforcement Rule|許容する通信帯域やDSCP値の付与など転送パケットのQoSに関して規定する|
|URR|Usage Reporting Rule|関連付けられたPDRが検知したパケットのカウント方法や、C-Plane装置に対するカウント状況の通知タイミングを規定する|
|MAR|Multi-Access Rule|5G用のルール。ATSSS機能をサポートする際に定義する必要がある規定。ATSSS: Access Traffic Steering, Switching and Splitting |
|SRR|Session Report Rule|PFCPセッションにおける特定のPDRに関わらない、またはトラヒック使用量に関わらないPFCPセッションのイベントを検出・報告について規定する|

# 参考
[トラフィック特性に応じた柔軟なU-Plane処理を実現するCUPSの開発](https://www.docomo.ne.jp/binary/pdf/corporate/technology/rd/technical_journal/bn/vol29_3/vol29_3_006jp.pdf)
[3GPP Technical Specification 29.244](https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3111)
機械学習に役立つ画像収集ライブラリ「icrawler」を使ってみた

## 動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/47Jl-_0wQHM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## 検証

皆さん、機械学習をするにあたり学習データの収集に苦労したことはないでしょうか。
今回は、学習するにあたり役に立つライブラリ「icrawler」を紹介します。

ライブラリの詳細については、github(@[gist](https://github.com/hellock/icrawler)
)を確認して頂ければ良いですが、簡単に言えばWebクローラーです。

画像サイトのFlickrだけでなく、Google、Bing、Baiduの検索エンジンも利用することができます。
では、実際にサンプルコードを書いていきます。

まずは、インストールをしましょう。
```
pip install icrawler
```

インストールができましたら、コードを書いていきます。
```
from icrawler.builtin import GoogleImageCrawler

google_crawler = GoogleImageCrawler(storage={'root_dir': 'test'})
google_crawler.crawl(keyword='aurora', max_num=100)
```
たった3行で書くことができました。
では、中身を見ていきましょう。
![](https://storage.googleapis.com/zenn-user-upload/69b975ee6eff-20220904.png)

見て頂くと確認できると思うのですが、約20%ほどノルウェー出身のシンガーソングライターのAURORAが含まれていることができますね。
もし、機械学習をするのであれば、データクレンジングをしていく必要がありますね。
Javaで何か作ってみる(2022/10/29 Day9)

## 今日やった事
- Udemyの動画教材を少し見た。（**J1-13_その他の制御構文** まで見た。）
## 参考にしたもの
- [【超絶丁寧解説】Javaプログラミングをゼロから学ぶ！絶対挫折させない「基礎入門」講座【講師評価4.3】](https://www.udemy.com/course/uz-java-kiso/)
    &rarr; Javaの勉強に使用しているUdemyの動画教材。
## 所感
- 今日も日中はバタバタして出来ず、寝る前の勉強になってしまった。
- GitHubの整理も出来なかった。
- 内容理解は完璧。
## 明日の予定
- 引き続き、動画教材を進めていく。
Javaで何か作ってみる(2022/10/28 Day8)

## 今日やった事
- Udemyの動画教材を少し見た。（**J1-11_繰り返し～while～** まで見た。）
## 参考にしたもの
- [【超絶丁寧解説】Javaプログラミングをゼロから学ぶ！絶対挫折させない「基礎入門」講座【講師評価4.3】](https://www.udemy.com/course/uz-java-kiso/)
    &rarr; Javaの勉強に使用しているUdemyの動画教材。
## 所感
- 今日は日中はバタバタして出来ず、寝る前の勉強になってしまった。
- GitHubの整理も出来なかった。
- 内容理解は完璧。
## 明日の予定
- 引き続き、動画教材を進めていく。
postgresqlに接続するとSSLが有効になってないため弾かれる場合の対処方法

# はじめに

`golang-migrate` で`postgresql`に接続して`migrate`を試みたところ、以下のエラーが発生した。

調べたところ、`postgres`コンテナーがデフォルトで `SSL` を有効にしないために起こるとのことだったので対処方法をまとめる。

```bash
migrate -path db/migration -database "postgresql://username:password@localhost:5432/dbname" -verbose up
2022/10/30 17:19:16 error: pq: SSL is not enabled on the server
```

https://www.postgresql.jp/docs/9.2/libpq-ssl.html

https://github.com/golang-migrate/migrate/tree/master/cmd/migrate

# 対処方法

`?sslmode=disable`をデータベースURLに追加することで接続が可能になります

```bash
migrate -path db/migration -database "postgresql://username:password@localhost:5432/dbname?sslmode=disable" -verbose up

2022/10/30 17:21:06 Start buffering 1/u init_schema
2022/10/30 17:21:06 Read and execute 1/u init_schema
2022/10/30 17:21:06 Finished 1/u init_schema (read 9.189788ms, ran 32.894114ms)
2022/10/30 17:21:06 Finished after 50.370077ms
2022/10/30 17:21:06 Closing source and database
```
【GAS】Instagram Graph APIを使って他ユーザーの投稿画像を自動取得するbotを作った

## はじめに
Instagram Graph APIの勉強も兼ねて、投稿情報の自動収集ツールを作りました。
ユーザーIDを入れると、投稿日・いいね数・コメント数・画像URL・動画URLをスプレッドシートに取得してくれます。
今回はクリスティアーノ・ロナウドの投稿を取得してみます。

## 完成品はこんな感じ
https://twitter.com/glbyel63c71/status/1586637400419160064?s=46&t=tbQWcP5uRU-TrqEDN1eQRw

## 手順
1. Instagram Graph APIの設定 （最難関）
2. APIからJSON形式で投稿情報を取得
3. JSONから必要な箇所を抽出して整形
4. シートに書き込む

### 1. Instagram Graph APIの設定 （最難関）
大変なので割愛。

必要なもの
- 有効期限なしのアクセストークン
- InstagramビジネスアカウントのユーザーID

### 2. APIからJSON形式で投稿情報を取得
~~~ javascript:
// Instagram Graph APIから画像情報をjson形式で取得する関数 (username, limit) -> json
function getPostImage(username, limit) {
  const USER_ID = ScriptProperties.getProperty('USER_ID');
  const ACCESS_TOKEN = ScriptProperties.getProperty('ACCESS_TOKEN') ;

  const url = "https://graph.facebook.com/v15.0/" + USER_ID +"?fields=business_discovery.username(" + username+ ")%7Bmedia.limit(" + limit + ")%7Btimestamp%2Clike_count%2Ccomments_count%2Cmedia_url%2Cchildren%7Bmedia_url%7D%7D%7D&access_token=" + ACCESS_TOKEN;
  
  const response = UrlFetchApp.fetch(url).getContentText();
  const response_json = JSON.parse(response).business_discovery.media.data;

  return response_json;
}
~~~
該当部分のソースコードはこんな感じ。

グラフAPIエクスプローラでフィールドをいじって投稿情報が取得できるかを確認し、
**「< / >コードを取得」** → **「cURL」** → **「OK」** でURLは取得できます。

https://developers.facebook.com/tools/explorer/

その後、ユーザーIDとアクセストークンをスクリプトプロパティから、ユーザーネームとlimitをセルから取得する形に変更しました。

### 3. JSONから必要な箇所を抽出して整形
~~~ javascript:
// mediaオブジェクトを成形する関数 json -> array
function formatPost(post_json) {
  let formatted_data = [];

  formatted_data.push(post_json.id);
  formatted_data.push(post_json.timestamp);
  formatted_data.push(post_json.like_count);
  formatted_data.push(post_json.comments_count);

  if(post_json.hasOwnProperty('children')){
    const children = post_json.children.data;

    let images_url = '';

    for(child of children){
      images_url += child.media_url + '\n'
    }
    images_url = images_url.slice(0, -2);
    formatted_data.push(images_url);
  }
  else formatted_data.push(post_json.media_url);

  console.log(formatted_data);
  return formatted_data;
}
~~~
ソースコードはこんな感じ。
シートに書き込むデータは配列にしなければならないため、この関数で成形しています。

また、投稿のjsonデータは画像が複数枚ある場合はchildrenというオブジェクトが入れ子になっているため、投稿画像が1枚or複数枚で分岐させてます。

投稿画像が複数ある場合は、1つのリンク毎に改行した文字列を返します。
この場合、1つのセルに複数のリンクが存在することになるので別途処理が必要になりました（後述）。

### 4. シートに書き込む
~~~javascript:
for(post of posts){
    if(!hasID(post.id)){ // 未取得の投稿のみ書き込む
      const post_info = formatPost(post); // json形式の投稿情報を書き込み用に成形
      sheet.appendRow(post_info);
    }
    else continue;
}
~~~
1投稿毎にシートに取得済みかどうかをhasID関数で確認し、未取得であれば成形して1行ずつ書き込みます。

~~~javascript:
// メディアIDが存在するかを判定する関数 id -> bool
function hasID(id) {
  const sheet = SpreadsheetApp.getActiveSheet();
  const ids = sheet.getRange(3, 1, sheet.getLastRow()-1).getValues();

  return ids.some(function(array, i, ids){
    return (array[0] == id);
  })
}
~~~
hasId関数は投稿に紐づいたメディアIDというユニークな番号で未取得かどうかを判定します。

## 困ったところ
- APIのアクセストークンの取得

- 1つのセル内に複数リンクの設定

- オフセットの設定がわからん
このスクリプトでは「最新の投稿から◯件取得」のような仕様になっているため、めちゃくちゃ古い投稿を取得するのは困難（1000件くらいなら余裕だが、10000件とかになると怪しい）。リファレンスを読み込んでいないので、知っている方がいたらコメントください。
【android】ボタンクリック時のイベント

## はじめに
ボタンをクリックしたときに、テキストボックスの文字を変更してみようと思います。
Hello World!⇒こんにちは
こんにちは⇒HELLO
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689436/6bcd3b4d-9545-6844-2a25-1669687bd3d9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689436/585c0146-a0f8-1e08-3bbe-b8f68edbd847.png)

### java
```java:MainActivity.java
package com.example.testapp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private TextView txt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txt = (TextView)this.findViewById(R.id.text1);
    }

    //ボタン（こんにちは）
    public void japButton(View view){
        txt.setText(R.string.temp1);
    }

    //ボタン（HELLO）
    public void japButton2(View view){
        txt.setText(R.string.temp2);
    }
}

```
まず、```onCreate()```でレイアウトパッケージの「text1」という名前の文字列プロパティを取得しています。
```japButton```と```japButton2```はボタンが押された時のイベントのメソッドです。


### XML
```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <Button
        android:id="@+id/out_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="japButton"
        android:text="@string/out_button_label"
        tools:ignore="UsingOnClickInXml" />


    <Button
        android:id="@+id/out_button2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="japButton2"
        android:text="@string/out_button_label2"
        tools:ignore="UsingOnClickInXml" />

</LinearLayout>
```
```android:onClick=```でイベントを定義しているメソッドを指定しています。

```xml:strings.xml
<resources>
    <string name="app_name">TestApp</string>
    <string name="out_button_label">こんにちは</string>
    <string name="out_button_label2">HELLO</string>
    <string name="temp1">こんにちは</string>
    <string name="temp2">HELLO</string>
</resources>
```
ボタンや、テキストボックスに表示する。文字列を定義しています。

## おわりに
htmlがxmlでjavascriptがjavaみたいなイメージですね。
java側で判定して、ボタンの数を増やしたりもできるのでしょうか、、
paiza.ioでelixir その30

# 概要
paiza.ioでelixirやってみた。
xmerl使ってみた。

# サンプルコード

```
defmodule XmlNode do
	require Record
	Record.defrecord :xmlAttribute, Record.extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl")
	Record.defrecord :xmlText, Record.extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl")
	def from_string(xml_string, options \\ [quiet: true]) do
		{doc, []} =
			xml_string
			|> :binary.bin_to_list
			|> :xmerl_scan.string(options)
		doc
	end
	def all(node, path) do
		for child_element <- xpath(node, path) do
			child_element
		end
	end
	def first(node, path), do: node |> xpath(path) |> take_one
	defp take_one([head | _]), do: head
	defp take_one(_), do: nil
	def node_name(nil), do: nil
	def node_name(node), do: elem(node, 1)
	def attr(node, name), do: node |> xpath('./@#{name}') |> extract_attr
	defp extract_attr([xmlAttribute(value: value)]), do: List.to_string(value)
	defp extract_attr(_), do: nil
	def text(node), do: node |> xpath('./text()') |> extract_text
	defp extract_text([xmlText(value: value)]), do: List.to_string(value)
	defp extract_text(_x), do: nil
	defp xpath(nil, _), do: []
	defp xpath(node, path) do
		:xmerl_xpath.string(to_char_list(path), node)
	end
end

doc = XmlNode.from_string("""
	<root>
		<child id="1">ai</child>
		<child id="2">ue</child>
	</root>
""")

Enum.each(XmlNode.all(doc, "//child"), fn(node) ->
	IO.puts "#{XmlNode.node_name(node)} id=#{XmlNode.attr(node, "id")} text=#{XmlNode.text(node)}"
end)

IO.puts(
	doc
	|> XmlNode.first("//child[@id='2']")
	|> XmlNode.text
)

IO.puts(
	doc
	|> XmlNode.first("//child[@id='3']")
	|> XmlNode.text
)

IO.puts(
	doc
	|> XmlNode.first("//root")
	|> XmlNode.first("child[@id='1']")
	|> XmlNode.text
)




```

# 実行結果

```
child id=1 text=ai
child id=2 text=ue
ue

ai
```

# 成果物

https://paiza.io/projects/Kxzd8D8hOkboTPsJT_PPlQ


以上。