OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScript  random関数

# 初学者の備忘録
初学者の備忘録です。今回はJavaScriptのrandom関数の基礎と簡単な演算子を記録していきたいと思います。


## random関数とは
random関数とはランダムな返り値（戻り値）を出す関数です。
random関数には`let 変数名　= parseInt Math.random()`を使用します。この状態だと小数点まで変え値としてしまうので自然数として出力するには少し工夫が必要になってきます。


## random関数基礎
上記での説明した通り、random関数を使用するには`let 変数名　= parseInt Math.random()`を使用します。
そして今回はサイコロのをイメージして１〜６の数字をランダムに出力させることをやっていきます。

```JavaScript
let randomum = parseInt(Math.random() * 6) + 1;
console.log(randomum);
```

上記のコードで１〜６の数字がランダムで出力されるようになります。
詳しく説明するとletでrandomumという変数名を作成し、parseInt(Math.random())でランダムな数字が一つ選択されます。ただし、このままでは小数点を含んだ数字がランダムで選ばれてしまうので、自然数で１〜６という制限をかけます。
　
 そこでMath.random()に✖️６をしてあげることで０〜６の間で選ばれるようになります。`parseInt(Math.random() * 6)`つまりここでの６という数字はどこまでの数値をランダムで出力させるのか？という制限になるのでランダムに出力させたい状況によって自由に変更可能です。

 最後に0〜６ではなく、１〜６の間でランダムに出力して欲しいので＋１をしてあげることで０という数字が出力されないようになります。`parseInt(Math.random() * 6) + 1`
＊６がランダムのどこまでと上記で説明したようにここでの＋１はどこからの数値になります。なのでここで１ではなく、＋３とすると３〜６の間となります。
　
 あとは`parseInt(Math.random() * 6) + 1`ここで選ばれたランダムな数値が返り値として変数randomumに格納され、console.logは出力コマンドなので１〜６のランダムな数値が出力されるというコードになります。


## random関数簡単演算子
ちょっとしてステップアップとしてrandom関数を使用して簡単な演算子をやっていきたいと思います。

リンゴの単価をランダムでリンゴの個数もランダムとした時、合計金額を出力する計算です。

```JavaScript
//リンゴの単価
let apple_price = (Math.floor(Math.random() * 3) + 1) * 100;
//リンゴを買う数
let apple_num = Math.floor(Math.random() * 10) + 1;

console.log("リンゴの単価：" + apple_price + "円");
console.log("リンゴを買う数：" + apple_num + "個");

// 合計金額
let total = apple_price * apple_num;
console.log("合計金額：" + total + "円");
```

基本的には基礎編とあまり変わりません。
Math.floor小数点切り捨ての関数です。リンゴの単価の部分は少し複雑そうに見えますが、(Math.floor(Math.random() * 3) + 1)の部分は基礎編の考え方と一緒で１〜３までの数値をランダムで選択します。しかしランダムで選択さされた数値を（）で囲み＊１００しているので返り値に＊１００と掛け算されるので１００、２００、３００のどれかの数値になります。
　
 合計金額の部分も難しく考えず、変数　＊　変数ということは返り値　＊　返り値と一緒なので単価　＊　個数となり、合計金額が出力されます。


## 最後
今回は基礎ではあるのですが、説明する箇所が多く、文章が冗長になってしまい自分でもうまくまとめられているのか不安です。間違いなどありましたら申し訳ありません。
以上で終了になります。お疲れさまでした。
【Swift】CIFilterで画像の露出度を調整する

# はじめに
CIFilterで画像の露出度を調整してみます

# サンプルアプリ
![Simulator Screen Recording - iPhone 15 - 2023-10-27 at 21.48.56.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/3c32c2ce-b1ce-96b7-0656-409ed0971662.gif)

# 実装
```swift
import SwiftUI

struct ContentView: View {
    private let image = UIImage(named: "sample1")!

    @State private var uiImage: UIImage?
    
    @State private var exposure: CGFloat = 0

    var body: some View {
        ScrollView {
            VStack {
                if let uiImage {
                    Image(uiImage: uiImage)
                        .resizable()
                        .scaledToFit()
                } else {
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFit()
                }

                HStack(spacing: 15) {
                    Button {
                        applyExposureAdjust()
                    } label: {
                        Text("適用")
                    }

                    Button {
                        uiImage = nil
                        exposure = 0
                    } label: {
                        Text("リセット")
                    }
                }
                
                VStack {
                    Text("露出度: \(exposure)")
                    Slider(value: $exposure, in: 0...10)
                }
            }
            .padding(.horizontal, 20)
        }
    }

    func applyExposureAdjust() {
        let context = CIContext()
        let inputImage = CIImage(image: image)!

        guard let filter = CIFilter(name: "CIExposureAdjust", parameters: [
            kCIInputImageKey: inputImage,
            kCIInputEVKey: exposure
        ]) else { return }
        guard let outputImage = filter.outputImage else { return }
        guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else { return }
        self.uiImage = UIImage(cgImage: cgImage)
    }
}
```

# おわり
最近CIFilterの記事ばっか書いてる気がしますw
モバイルアプリのリリース毎の変化を一覧で確認

# 概要
モバイルアプリのリリースをした際に、**「最新のリリースが結果としてユーザーに良い体験を提供できているのか？」**、**「逆にリリースによってパフォーマンスや体験の悪化が発生していないか？」** など、リリース後に気になることは沢山あります。

New Relicの9月のアップデートで、モバイルアプリのバージョン視点で柔軟な傾向分析ができるようになったので画面を確認していきたいと思います。

:::note info
最新のアップデートの詳細はこちら。[New Relic アップデート(2023年9月)
](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202309 "New Relic アップデート(2023年9月)")
:::

公式ガイドはこちらです。

https://docs.newrelic.com/jp/docs/mobile-monitoring/mobile-monitoring-ui/mobile-app-pages/version-trends-compare-user-adoption-metrics-performance/

# リリースバージョンごとの一覧画面を確認
New Relicにログインして、[Mobile] > [Release versions]を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/bc1015ae-c9aa-6931-d0f1-05a65013b519.png)


すると、画面の右側上のタイムピッカーで指定されている期間にNew Relicに取り込まれたデータをもとに、各リリースバージョンごとの **Overall performance score**、**Cash-free user**、**User adoption** が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/f1dc3b5b-dc08-0f67-fe94-3dc606b965e5.png)

各項目の意味合いは次の通りです。

| 項目 | 内容 |
|:-|:-|
|Overall performance score| 全体的なパフォーマンススコア |
|Cash-free user| クラッシュが発生していないユーザーの割合 |
|User adoption| ユーザーが利用している割合 |

# 各バージョンの詳細画面を確認

さらに、各バージョンの **View summary** や **View details** をクリックすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/046a0d51-1a31-c604-a035-8fce4c6cc48e.png)

そのバージョンの詳細画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227243/c57a2744-4ed0-bba5-bf81-1b26db2e6d2c.png)

下記の項目毎に **数値** と **前回リリースからの変化率(%)** を確認することができます。

| 項目 | 内容 |
|:-|:-|
|App Launches|アプリの起動回数| 
|Average Interaction Time|平均インタラクション時間| 
|Average Memory Used |平均メモリ使用量| 
|Average Response Time|平均応答時間| 
|Crash Rate|クラッシュ率| 
|Error Rate|エラー率|
|HTTP Error Rate |HTTPエラー率| 
|Install Count |インストール数| 
|Network Failure Rate|ネットワーク失敗率| 
|Request Count|リクエストの数| 
|Total Users|操作したユーザーの数| 
|Upgrade Count|アップグレードしたユーザーの数|                                               

例えば、クラッシュ率やエラー率で変化を確認することで、最新リリースによって**ユーザー体験に悪影響を与えていないか**把握することができますし、平均応答時間を見ることで**アプリがサクサク動いているか**客観的な数値で判断することができます。

# まとめ
New RelicのMobileエージェントを使ってデータを取り込むとバージョン情報も合わせて取得しているため、**バージョンごとでの情報を可視化**して、その**変化を捉えることが可能**です。
最新リリースと過去のリリースを継続的に比較して、よりよりユーザー体験を提供するための指標としていただけると幸いです。

:::note info
最新のアップデートの詳細はこちら。[New Relic アップデート(2023年9月)
](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202309 "New Relic アップデート(2023年9月)")
:::

:::note info
[New Relic株式会社のQiita Organization](https://qiita.com/organizations/newrelic)では、
新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::
CyberChef

<!--
2023/10/25
-->

[picoCTF][Cryptography][rotation]

## Writeup
* Rot13を試したけど、ダメだった。
BruteForceしたら、OKだった。
![screenshot 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/caa04c1c-530a-b90a-c48d-707de89423ea.png)
<br>

* 以上です。
Polarsは速いだけじゃなくて可読性もいいぞ

2024-06-12 polars 1.0.0-alpha.1 でWarningが出ないよう修正しました。

# 先駆者

https://qiita.com/_jinta/items/394b1682893e5991d592

https://qiita.com/_jinta/items/fac13f09e8e8a5769b79

# 本文

[データサイエンス100本ノック（構造化データ加工編）](https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess) P-069

> レシート明細データ（df_receipt）と商品データ（df_product）を結合し、顧客毎に全商品の売上金額合計と、カテゴリ大区分コード（category_major_cd）が"07"（瓶詰缶詰）の売上金額合計を計算の上、両者の比率を求めよ。抽出対象はカテゴリ大区分コード"07"（瓶詰缶詰）の売上実績がある顧客のみとし、結果を10件表示せよ。

問題文の逐語訳レベルで書ける！！！

```py: Polars
(
    # レシート明細データ（df_receipt）と商品データ（df_product）を結合し、
    df_receipt
    .join(df_product, on="product_cd", how="inner")
    # 顧客毎に
    .group_by("customer_id").agg(
        # 全商品の売上金額合計と、
        sum_all=pl.sum("amount"),
        # カテゴリ大区分コード（category_major_cd）が"07"（瓶詰缶詰）の売上金額合計を計算の上、
        sum_07=pl.col("amount").filter(pl.col("category_major_cd") == "07").sum(),
    )
    # 両者の比率を求めよ。
    .with_columns(sales_rate=(pl.col("sum_07") / pl.col("sum_all")))
    # 抽出対象はカテゴリ大区分コード"07"（瓶詰缶詰）の売上実績がある顧客のみとし、
    .filter(pl.col("sum_07") > 0)
    .sort("customer_id")  # pandas版と合わせる
    # 結果を10件表示せよ。
    .head(10)
)
```

```py: Pandas: データサイエンス100本ノック（構造化データ加工編） コード例1より引用&コメント追記
# 顧客毎に全商品の売上金額合計と、
df_tmp_1 = df_receipt.groupby('customer_id').agg({'amount':'sum'}). \
                reset_index().rename(columns={'amount':'sum_all'})

# カテゴリ大区分コード（category_major_cd）が"07"（瓶詰缶詰）の売上金額合計を計算の上、
df_tmp_2 = pd.merge(df_receipt, df_product.query('category_major_cd == "07"'), 
                how='inner', on='product_cd').groupby('customer_id').\
                agg({'amount':'sum'}).reset_index().\
                rename(columns={'amount':'sum_07'})

# レシート明細データ（df_receipt）と商品データ（df_product）を結合し、
# 抽出対象はカテゴリ大区分コード"07"（瓶詰缶詰）の売上実績がある顧客のみとし、
df_tmp_3 = pd.merge(df_tmp_1, df_tmp_2, how='inner', on='customer_id')

# 両者の比率を求めよ。
df_tmp_3['sales_rate'] = df_tmp_3['sum_07'] / df_tmp_3['sum_all']

# 結果を10件表示せよ。
df_tmp_3.head(10)
```

```py: Pandas: メソッドチェーンで書いた場合
(
    # レシート明細データ（df_receipt）と商品データ（df_product）を結合し、
    df_receipt
    .merge(df_product, on="product_cd", how="inner")
    # カテゴリ大区分コード（category_major_cd）が"07"（瓶詰缶詰）の売上金額合計
    .assign(amount_07=lambda df: df["amount"] * (df["category_major_cd"] == "07"))
    # 顧客毎に
    .groupby("customer_id").agg(
        # 全商品の売上金額合計と、
        sum_all=("amount", "sum"),
        # カテゴリ大区分コード（category_major_cd）が"07"（瓶詰缶詰）の売上金額合計を計算の上、
        sum_07=("amount_07", "sum"),
    )
    # 両者の比率を求めよ。
    .assign(sales_rate=lambda df: df["sum_07"] / df["sum_all"])
    # 抽出対象はカテゴリ大区分コード"07"（瓶詰缶詰）の売上実績がある顧客のみとし、
    .query("sum_07 > 0")
    # 結果を10件表示せよ。
    .head(10)
)
```

# notebook
https://gist.github.com/n-takumasa/d0243b6109ffeb37edc8da43fd179834
[OutSystems]CI/CD Probe 2.2.0の更新内容を確認

2023/10に、OutSystemsでCI/CDを実現するのに使うForgeコンポーネントのアップデートが来ていたので更新内容を確認しておく。

# 環境情報
Personal Environment(Version 11.23.0 (Build 39357))
Service Studio(Version 11.54.30)
[CI/CD Probe](https://www.outsystems.com/forge/component-overview/6528/ci-cd-probe)(Version 2.2.0)

# Expose REST APIに認証が追加された
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/dcbc54d2-9011-0ce1-63cb-d4d9dd261b25.png)

Site Propertyに「Feature_EnableAPIKey（Boolean型）」が追加されている。有効になっていると、API呼び出し時のHTTPヘッダーに「X-CICDProbe-Key」というキーで渡さないとエラー（Status Code=401）になる。
渡したキーはSite Property「APIKey」と一致している必要がある。

では、Site Propertyはどこで設定されるかというと、「GenerateAPIKey」というTimerが追加されており、When Publishedに設定されている（つまりモジュールのPublish時にパスワードが生成される）。
パスワード生成はSite Propertyが未設定のときのみ行われる。

## 動作確認
### まずは何も設定せずにアクセス
CI/CD Probeが提供するAPI定義を使い、OutSystemsのConsume REST APIを作る。
（ざっくりした手順は
1. CI_CDProbeモジュールのLogicタブ > REST/v2を右クリック
1. Open Documentation
1. 「swagger json」のリンクを右クリックしてアドレスをコピー
1. テスト用モジュールを開く
1. Logicタブ > RESTを右クリックし、Consume REST API...を選択
1. Add multiple methodsを選択してContinueボタン
1. コピーしておいたURLを貼り付けてAdd methods⇒Finishボタン）

作成されたAPIにAPIKeyを特に渡さずに実行しても問題なく動作する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/53a9aa5e-af50-5082-0273-03ac3d184722.png)

これは、Site Propertyのフラグを立てていないため。

### 認証を有効にしてテスト
Site Property 「Feature_EnableAPIKey」はデフォルトでFalseなので、Trueにする。
この状態で↑と同じActionを実行すると例外が発生する。

例外のメッセージは「401 Unauthorized」。

そこで、必要なAPIKeyを渡すように変更する。

まずはConsume REST APIの対象を右クリック⇒Add Input Parameter
設定は以下の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/e5f46a92-a51a-ba36-f530-0992c489c368.png)
- Send In: APIKeyはヘッダで渡すという指定がされているので、Headerを選択
- Name in Request: X-CICDProbeKeyとする。これはCI/CD ProbeのGetAPIKeyHeader Actionでこの名前でヘッダーを取得しているため
- Log Redaction: APIKeyは一応機微な情報なのでログに出さないようにYesにしておく

あとは、Consume REST APIを実行する場所で、APIKey Input ParameterにCI/CD ProbeのSite Property「APIKey」からコピーしてきた値を設定するだけ（値はService Centerで確認する）。

# BDDFramework Client Sideで作られたテストに対応するAPIの新バージョン
Expose REST APIは元々v1しかなかったが、v2が追加。
v2のScamBDDTestEndpoints Methodの実装は以下の通り変わっている。
- 最初にBDDFrameworkで作られたテストモジュールを検索するSQL要素が、「BDDFrameworkを参照するモジュールとBDDFramework Client Sideを参照するモジュールのUNION」を取るように変わった
- テストモジュールから画面を抽出するためのOutDoc内のAction Section_3_2_GenerateWebScreenのIsNewRuntimeにTraditional（値はFalse、BDDFramework向け）かMobile（値はTrue,BDDFramework Client Side向け）を渡すようになった

この変更は、以前書いた[CI/CD Probeを微修正して、BDDFramework Client Sideのテストを抽出する](https://qiita.com/jyunji_watanabe/items/17a1ede33aebd08ad9b1)で見た内容と同じ。
なので、わからない点はそっちを見てもらえればたぶん分かるかと。

# BDDFrameworkモジュールが名称変更されていても動作するようになった
v2 APIでBDDFrameworkを参照するモジュールを検索する際に、BDDFrameworkのモジュール名ではなく、SS_Keyを利用するようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/0ad8b32d-0c7d-5643-7582-34dc31194167.png)

SS_Keyは、「BDDFrameworkClientSide_ModuleKey」「BDDFramework_ModuleKey」に設定する（デフォルト値が設定されているので、通常何もする必要はないはず。ただしBDDFrameworkをCloneしていたりすると別）。
OctoStudioで本格的なスマホアプリに挑戦しよう

# 「本格的なプログラミング言語」とは

次のような考えを耳にする（読む）ことがあります。

```
Scratchでプログラミングの概念を学んだら、本格的なプログラミング言語を習得しましょう。
```

でも、 **「本格的なプログラミング言語」** ってなんでしょうか。
Scratchもまた **本格的なプログラミング言語** なんですけどね。


# 同級生に遊んでもらうゲームを開発する高校生

知り合いの高校生が、Scratchでゲームを開発しています(2023年10月現在)。
**「どうして、Scratchで開発するの？」** と聞いたところ、
**「学校の友達にも遊んでもらいたいから。iPhoneとかAndoridとかで。」** とのことでした。

彼は、iPadのブラウザーで開発し、友達はスマホのブラウザーでゲームを楽しんでいるようです。

# 本格的なスマホアプリ開発環境 - OctoStudio

とうとう、2023年10月24日に [OctoStudio](https://octostudio.org/ja/) がリリースされました。
[プレスキット:https://www.media.mit.edu/projects/octostudio/press-kit/](https://www.media.mit.edu/projects/octostudio/press-kit/)

この [OctoStudio](https://octostudio.org/ja/) は、子ども向けで世界で最も人気のあるプログラミング言語であるScratchを作成した **MITメディアラボ Lifelong Kindergarten グループ** によって開発されました。

https://octostudio.org/ja/

iPhoneやAndroidのスマホで、カメラやセンサー、スマホ間メッセージを使ったアプリを開発でき、その開発したアプリを配布できるのです。

**【開発例】「ようこそ！」スマホアプリのGIF録画**

![ようこそ!.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/9010d62f-0230-098f-668d-7072e9245850.gif)


# さいごに

さて、どのようなスマホアプリを開発しましょうか。
Djangoの学習②（アプリの作成からビューの作成まで）

投票アプリを作成して行きます

その前に、ここでそもそもプロジェクトとアプリの関係性について言及されていますね

:::note
プロジェクトとアプリケーション

プロジェクトとアプリの違いは何でしょうか？ 
アプリとは、ブログシステム、公的記録のデータベース、小規模な投票アプリなど、
何かを行う Web アプリケーションです。
プロジェクトは、特定のウェブサイトの構成とアプリのコレクションです。
プロジェクトには複数のアプリを含めることができます。 
アプリは複数のプロジェクトに存在できます。
:::

とのことです

プロジェクトは既にmysiteとして作成しているので
mysite内にpollsアプリを作成していきます

## pollsアプリの作成

アプリを作成するには、
manage.pyのあるmysiteプロジェクトディレクトリにいることを確認し、
次のコマンドを入力します。

```
$ python manage.py startapp polls
```

pollsディレクトリが作成されていることを確認します

```
$ ls

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        2023/10/24     19:12                migrations
-a----        2023/10/24     19:12             66 admin.py
-a----        2023/10/24     19:12            148 apps.py
-a----        2023/10/24     19:12             60 models.py
-a----        2023/10/24     19:12             63 tests.py
-a----        2023/10/24     19:12             66 views.py
-a----        2023/10/24     19:12              0 __init__.py
```


## 最初のビューの作成

以下、元のファイルに公式のTutorialのコードを追記という形になります

```python:polls/views.py
from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
```


polls/urlsファイルにパスを記述
（３行目のコードについてはよくわかってないです）

```python:polls/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path("", views.index, name="index")
]
```

今度はルートの方のurlsファイルに設定を記述

```python:mysite/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]
```

リローディングします
```
$ python manage.py runserver
```

http://localhost:8000/polls/
にアクセスします


Hello, world. You're at the polls index.

と表示されていれば成功です。
steghide

<!--
2023/10/24
-->
[picoCTF][Cryptography][HideToSee]

## Writeup
* steghideをインストール
そして実行。パスワードはなしで。
~~~
sudo apt install -y steghide
steghide extract -sf atbash.jpg
~~~
* ファイルを確認
![screenshot 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/a9e3a805-29f5-7219-d9e6-ed096dd4bd05.png)
<br>

* 出てきた文字列をCyberChefで。
![screenshot 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/d25d6b0d-82ec-6847-562c-6ae3bd7e094c.png)
<br>

* 以上です。

## 参考サイト
https://steghide.sourceforge.net/
Mac上のUbuntu ターミナルでキー配列を日本語（JIS配列）にする

# きっかけ
vimで`:`がスっと打てないのが嫌でターミナルのキー配列をJIS配列にしようと思ったのですが，巷に出回ってる記事の方法だとどうしてもできないので，自分で試行錯誤していたところ，解決方法を発見したので共有します．もしかするとAppleシリコンのMacの仮想環境でUbuntuを動かす場合だとできないのかもしれないです．機能しなくなるキーが出てくる可能性が考えられるので，**実行する場合は自己責任でお願いします．**

# 筆者のマシン
### ホストOS
- チップ：Apple M1
- コアの総数：8（パフォーマンス: 4、効率性: 4）
- メモリ：8 GB

UTMの上でUbuntuを実行

# やり方
以下を叩く．
```console:terminal
sudo dpkg-reconfigure keyboard-configuration
```
以下の順に選択
1. Apple laptop
1. Japanese
1. Japanese
1. The default for the keyboard layout
1. No compose key
1. No

logoutして再ログイン．
AWSで起動したインスタンスへの接続方法

AWSのインスタンスにどうやって接続するのかわからなかったので残しておきます。

## インスタンス起動
新しいインスタンス起動時に**キーペアを作成**します。
任意のキーペア名を入力しキーペアを作成します。
キーペアが作成されたらそのキーが保存されていることを確認してください。

~~~
キーペア名：　任意
キーペアタイプ：　RSA
プライベートキーファイル：　.pem
~~~
作成したらインスタンスを起動します。

## インスタンスに接続
接続したいインスタンスを選択し`インスタンスに起動`を押します。
接続方法を`SSHクライアント`を選択し下部4番目の「ご使用のインスタンスのパブリックDNSを使用してインスタンスに接続」のコマンドをコピーします。

コピーしたらコマンドプロンプトを起動し、ペーストします。
~~~Bash
admin@ip-xxx: $
~~~
となれば成功です。
rex0220 計算式プラグイン 小数計算例

計算式プラグインでの小数計算例です。

# 概要

JavaScript で、小数計算を行うと２進数で小数計算を行うため誤差が出る場合があります。
計算式プラグインは、[bignumber.js](https://github.com/MikeMcl/bignumber.js)というライブラリを利用して、誤差がでないようにしています。
kitone 標準の計算項目では、API で計算を行っており誤差が出ないようになっているようです。

## 計算式プラグインの計算例
![2023-10-27_20h34_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a3beff50-81a1-376f-c6ae-3921f23422c9.png)

## JavaScript の計算例
編集画面では、誤差が表示されるが、レコード保存時に小数が丸められる。
![2023-10-27_20h37_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7898bc5c-efc2-fa14-a121-1f73deca46b0.png)
※kintone 標準の計算式で、数値3 と計算の項目を比較すると、数値が異なるにもかかわらず、数値が同じという〇が表示される。
比較前に小数の丸め処理が行われてると思われます。

## kintone 数値と計算の精度
アプリの高度な設定で、数値と計算の精度が設定される
![2023-10-27_20h51_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/e673a2f8-a308-9414-b468-8dbad5fe2341.png)

# kintone 標準の計算式

![2023-10-27_20h45_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a63ea761-b3cd-08c5-64d2-26d183fcbf90.png)

![2023-10-27_20h45_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d5f1e544-9205-62bb-a3bf-41b8591e24e9.png)

# 計算式プラグインの設定

![2023-10-27_20h44_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c33ba39d-c86e-5bf8-6a94-585cdb847226.png)

# JavaScript による計算

```.js
(function () {
    'use strict';
    let evs = [
        'app.record.create.show', 'app.record.edit.show',
        'app.record.create.change.テーブル', 'app.record.edit.change.テーブル',
        'app.record.create.change.数値1', 'app.record.edit.change.数値1',
        'app.record.create.change.数値2', 'app.record.edit.change.数値2',
    ];

    kintone.events.on(evs, (event) => {
        const record = event.record;
        record.テーブル.value.forEach((row) => {
            try {
                row.value.数値3.value = Number(row.value.数値1.value) + Number(row.value.数値2.value);
            }
            catch (error) {
                row.value.数値3.value = '';
            }
        });
        return event;
    });
})();
```
私的サーバー構築日誌：Dockerコンテナを自動起動する

# 能書き

[私的サーバー構築日誌：仕切り直し](https://qiita.com/katz_engineer/items/1f21de2bd9072c260ae6)からの自宅サーバー構築の続きです。

[以前Dockerコンテナを作成しました](https://qiita.com/katz_engineer/items/1896ae5fdc64de324ce8)が、Dockerコンテナはマシンを再起動すると停止してしまいます。マシンを起動した時に自動起動するような設定を模索しました。

# 目標

- マシン再起動時に、指定のDockerコンテナを自動起動する。
    - Dockerコンテナは docker compose で作成。

# 参考文献

- [Dockerデーモンやコンテナ、コンテナ内のサービスの自動起動方法の解説（Linux版） - めもたんす](https://www.memotansu.jp/docker/575/)
- [dockerのコンテナの自動起動をsystemdにて行う際の注意点について - めもたんす](https://www.memotansu.jp/docker/563/)
- [Docker Compose restart の挙動 - 技術備忘記](https://junchang1031.hatenablog.com/entry/2016/05/18/000605)

# 概要

Dockerには```restart```というオプションがある模様。恥ずかしながら知りませんでした。[参考文献](https://junchang1031.hatenablog.com/entry/2016/05/18/000605)参照。

これがわかれば、後はやってみるだけですな。

# やってみる

## Dockerコンテナの置き場所

まずは、今後を見据えて細かい決め事をします。

今後、```restart: unless-stopped```の設定でDockerコンテナを複数立てる事になると思われます。
その置き場所は、[管理者アカウント](https://qiita.com/katz_engineer/items/667aefcab488cc4a1caf#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)のhomeディレクトリに```docker-コンテナ名```ディレクトリを作成して置く事にします。

## テスト用Dockerコンテナ作成

```console:サーバー
cd
mkdir -p docker-test
cd docker-test
cat <<___ >docker-compose.yml
version: '3.8'
services:
  test:
    image: ubuntu:22.04
    build: .
    tty: true
    restart: unless-stopped
___
```

今回は```Dockerfile```は不要です。この```docker-compose.yml```だけでコンテナを起動します。

```console:サーバー
docker compose up -d
```

確認。

```console:サーバー
docker compose ls
```

例えば管理者ユーザー名がadminの場合、下記のようになります。

```console:サーバー
$ docker compose ls
NAME                STATUS              CONFIG FILES
docker-test         running(1)          /home/admin/docker-test/docker-compose.yml
```

```console:サーバー
sudo reboot
```

マシン再起動後、ログインして様子を見ます。

```console:サーバー
docker compose ls
```

確かにDockerコンテナが自動起動しているようです。

```console:サーバー
$ docker compose ls
NAME                STATUS              CONFIG FILES
docker-test         running(1)          /home/admin/docker-test/docker-compose.yml
```

念の為、Dockerコンテナにログインしてみましょう。

```console:サーバー
cd
cd docker-test
docker compose exec test /bin/bash
```

```console:コンテナ内
exit
```

ここで、Dockerコンテナを```stop```してみます。

```console:サーバー
docker compose stop
```

確認。

```console:サーバー
docker compose ls -a
```

止まったようです。

```console:サーバー
$ docker compose ls -a
NAME                STATUS              CONFIG FILES
docker-test         exited(1)           /home/admin/docker-test/docker-compose.yml
```

この状態でマシンを再起動してみます。

```console:サーバー
sudo reboot
```

今度はDockerコンテナは停止している筈。ログインして様子を確認します。

```console:サーバー
docker compose ls -a
```

確かに停止していました。

```console:サーバー
$ docker compose ls -a
NAME                STATUS              CONFIG FILES
docker-test         exited(1)           /home/admin/docker-test/docker-compose.yml
```

確認できたら、綺麗さっぱり後始末しましょう。

```console:サーバー
cd
cd docker-test
docker compose down --rmi all --volumes
cd ..
rm -r docker-test
```

# 仕舞い

マシン再起動時に、指定のDockerコンテナを自動起動できるようになりました。停止した場合には自動起動しません。理想的です！
若手エンジニア奮闘記④IT業界への挑戦

# はじめに

こんにちは！齊藤です。
IT未経験からIT企業に入社しました。まずは簡単な自己紹介です。
私は文系大学の出身で、勉強は必要最低限、パソコンも何とか使えるレベルで社会人1年目を迎えました。大学生活の中心はカフェでのアルバイト、旅行です。好きなことは、クラシックバレエで20年間やっています。こんなITとは無関係だった私は、将来性があり幅広く人の役に立てるという理由でIT業界に興味を持ちました。

# 想像以上に苦戦した研修

研修ではExcelの使い方、Microsoft Azureで仮想マシンの作成をしてwebサーバの構築、プログラミング言語ではVisual Studioを使いＣ＃で簡単なプログラミングを書くなど、私にとっては盛り沢山の内容です。学生から社会人になるということで勉強も1から頑張ると気合満々だった私は、入社1週間足らずでヒーヒー言ってました。講師の先生方や同期、先輩方に助けていただきながらなんとか研修を終えましたが、想像以上の難しさに家で泣いたこともありました。しかし研修内容が実際に配属後の現場で役に立っており、この経験が自身を成長させてくれました。

# 研修からの学び

研修では毎日毎日知らない言葉、問題がたくさん出てきます。それをノートに書き出してしつこく周りの人に質問する。このようなことを研修中はやっていました。ただプログラミング言語までいくと、どこが分からないのか、ここは質問するべき箇所なのかが分からなくなってきます。そんな時は一度離れて違う視点から見ることを教えていただきました。ひたすら机に向かうだけでなくYouTubeも活用する。時間をおいてもう一度チャレンジする。そうすることで少し理解に進展もありました。
また、パソコンの組み立て研修というものが私の会社にはあります。自分たちでパソコンの部品を買いに行くところからです。実際に自分の手でパソコンをつくることで用語や機能も覚えます。この研修はやっている時よりも、実際に配属後の現場で身に付いていると気が付きました。
講師の方の話を聞くという受け身な姿勢だけでなく、自分自身で入り込むことで理解力は高まるとわかりました。研修は内容だけでなく、勉強方法も学ばせてくれます。

# 楽しむことが大切

勉強ってつい他の人と自分を比べてしまいがちです。他の人の頑張っている姿を見てそれがモチベーションになることもあるのですが、研修中の私はその余裕もありませんでした。周りができているのに自分だけ置いていかれている気がして余計焦る。負のループです。そうならないためにも大切なのは楽しむことだと思っています。私はバレエを20年続けていますが、続く理由は単純に楽しいから！楽しいと続きます。もちろん辛いこともたくさんありましたが結局はどれだけ自分が楽しむかだと思います。

# 研修後の配属

私の配属先はPMOです。みなさんPMOってご存知でしょうか。
ちなみに私は入社直前まで知りませんでした。
機会があったらまた配属後のお話も！！

ご覧いただきありがとうございました！
業務で使用していたツール

以前の会社で業務で使用していたツールをご紹介いたします。

#### WinMerge

WinMergeとは、Windows上で比較・マージを行うためのオープンソースのプログラミング支援ツールです。 フォルダとファイル両方を比較でき、理解しやすく扱いやすいテキスト形式で差異をビジュアルに表現。

#### Rancher Desktop

Rancher Desktopはデスクトップ上でKubernetesとコンテナの管理を行うことができるツールです。containerdやDockerを使ってコンテナーイメージのビルド、プッシュ、ダウンロード、実行できます。

K3sを使ってKubernetesクラスターの実行もデスクトップ上で可能になっています。

Visual Studio CodeのRemote DevelopmentやDocker拡張機能などの導入によって、Rancher Desktopを使ってコンテナベースでアプリケーション開発も可能になっています。
Date.prototype.toString()

toString() メソッドは、指定した Date オブジェクトをローカルタイムゾーンで解釈したものを表す文字列を返します。

```
const event = new Date('August 19, 1975 23:15:30');

console.log(event.toString());
// Expected output: "Tue Aug 19 1975 23:15:30 GMT+0200 (CEST)"
// Note: your timezone may vary

```
Officeスクリプトを少し学習（PowerAutomateの流れで・・

## PowerAutomateを用いるため、その中でOfficeスクリプト（TypeScript）の学習
powerautomateで自動化を模索する中で、必要なため
セルのコピーを活用し、powerautomateで実行

この備忘録です。最近OUTPUTできていなかったため、ここらで投稿

### セルのコピー
エクセルのコピーを内部処理させたい（powerautomateへ自動化させるため）
これだと、なぜか内部エラー発生

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448426/728f37a2-7321-c8c4-9240-79bbca6b2c3d.png)

一括コピーOK
``` officescript.

function main(workbook: ExcelScript.Workbook) {
    // 作成用シートを取得
    let ws = workbook.getWorksheet("作成用");
    // 日付を文字列に変換
    let dateStr = new Date().getDate().toString();
    // 日付のシートが存在するかチェック
    let dateSheet = workbook.getWorksheet(dateStr);
    if (!dateSheet) {
        // 存在しない場合は新規作成
        dateSheet = workbook.addWorksheet(dateStr);
    }
    
    let copy = workbook.getWorksheet("25")
    //有効なセル範囲の値を取得する。
    let data = ws.getUsedRange().getValues();
    copy.getRangeByIndexes(0,0, data.length, data[0].length).setValues(data);

}
```

部分コピーも可能だった。
＊後で追記する。

### 参考
https://note.com/joji_o/n/n9baf2c75dda6

### メモ

直近
python
生成AIの学習
インフラ（ネットワーク、カメラ設置など）
powerapps
powerautomate
powerbi
IoT
MS365
社内セキュリティポリシー策定
インボイス対応

などなど広く業務に取りかかっており、すべて生成AIに助けられている。
最近OUTPUTが少ないため、少しずつOUTPUTも増やせるように継続していく。
Date.now (JavaScript) 

投稿日時はDate.nowという関数で取得できます。

Date.now() メソッドは、UTC (協定世界時) での 1970 年 1 月 1 日 0 時 0 分 0 秒 から現在までの経過時間をミリ秒単位で返します。

```
// This example takes 2 seconds to run
const start = Date.now();

console.log('starting timer...');
// Expected output: "starting timer..."

setTimeout(() => {
  const millis = Date.now() - start;

  console.log(`seconds elapsed = ${Math.floor(millis / 1000)}`);
  // Expected output: "seconds elapsed = 2"
}, 2000);
```
git apply

#### apply によるパッチの適用

git diff あるいは Unix の diff コマンドで作ったパッチ（パッチの作り方としては推奨できません。次節で理由を説明します）を受け取ったときは、git apply コマンドを使ってパッチを適用します。 パッチが /tmp/patch-ruby-client.patch にあるとすると、このようにすればパッチを適用できます。

````
git apply /tmp/patch-ruby-client.patch
````
git diff

#### git add する前に変更点を見る

````
git diff
````
git add する前に変更した箇所とインデックスとの変更点が見たいときはこのコマンドです。

````
git diff >ファイル名.diff
````
git add する前に変更した箇所の差分をファイルに出力するコマンドです
RDS MySQLサーバーの設定

※失敗例
環境：
OS：Amazon Linux 2023
セキュリティグループ：プライベートサブネット

NATゲートウェイの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/fd8ceac9-6035-7537-c4a2-d856f58ad617.png)

ルートテーブルを設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/cf657345-eed1-73f7-2efd-2dacc59143e5.png)

パブリックサブネットのEC2インスタンスに接続し、
DB用の秘密鍵ファイルを作成
```shell
sudo su
nano myprivatekey.pem
##秘密鍵をコピペして保存##
chmod 400 myprivatekey.pem
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/07f31368-a30d-3c41-de18-0b253d0e920d.png)

SSH接続する
```shell
ssh ec-2user@DBインスタンスのプライベートIPアドレス
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/6abcdfe5-8c40-0bd2-2013-cc7a45f8fa7c.png)

MySQLパッケージをインストールしていく
```shell
dnf localinstall https://dev.mysql.com/get/mysql80-community-release-el7-5.noarch.rpm -y
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/38b6bc8e-2d06-ec17-a568-9caf63f961c9.png)
```shell
dnf install mysql-community-server -y
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/01657ca7-2b8c-86db-38cc-fd04684869fe.png)
エラーでインストールできなかった。
```shell
wget https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
```
```shell
dnf localinstall mysql80-community-release-el7-7.noarch.rpm
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/54ce66b2-ed63-0598-0946-59228a228c9f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/67e8028e-bde9-7313-38c3-4c7097571234.png)
インストール完了？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/564e1ae2-1295-7973-8feb-fc4a4e40a850.png)
どうやらだめなようだ...
ちょっと探して...
以下で実行
```shell
dnf -y localinstall  https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm
dnf -y install mysql mysql-community-client
```
インストールはできたが
```shell
systemctl start mysqld
```
で実行できない。

Amazon Linux 2023 はMariaDBを推奨しているようです。
うーむ。
パスを結合する (path.join)

ディレクトリ名を表すパスと、ディレクトリ名あるいはファイル名を結合するには、Node.js の標準モジュール path が提供している path.join メソッドを使用します。

#### 例: 実行中のスクリプトのディレクトリ名と hello world.txtというファイル名を結合したパスを取得

```node.js
let path = require('path')
let filepath = path.join(__dirname, 'hello world.txt');
```
Content-disposition(こんてんと でぃすぽじしょん)

Content-dispositionとはHTTPヘッダの一つでHTML以外のファイルをWebブラウザに送信する場合につけられる。
いわゆるマルチパート・データ?の指定でありボディに含まれる添付ファイルの属性を指定する。
inlineはボディと一緒に表示され、attachmentは通常の添付ファイルとして扱う。
filenameはオリジナルのファイル名を伝える。
application/x-www-form-urlencoded(アプリケーション・エックス・フォーム・ユーアーエルエンコーディド)

application/x-www-form-urlencoded は、フォームの提出のための形式の1つです。 HTML のフォームの提出のために開発され、 HTTP POST の payload body や HTTP GET の URL query で使われています。 HTML に限らず、 OAuth や各種サービスの Web API などでも標準的な入力形式として採用されています。
IAMロールでCodeCommitにアクセスする方法（git-remote-codecommit）

# 目的
備忘録。

IAMロールで CodeCommit へアクセスする方法を共有し、それによるアクセス権限の制御（および場合によっては CodeCommit のコストダウン）を実現する。

# 背景
以前には Git 認証情報を使ったアクセスをしていましたが、ローテーションやPC移行等でいちいち Git 認証を発行して管理するのが面倒になりました。できればIAMロールでどうにかできないかと調べたときのメモです。
またWindowsの資格マネージャに認証情報が残らないのもいいですね。

# やり方
やり方は非常に簡単で、GRCのセットアップをした後にIAMロールの設定をしたプロファイルを指定するだけです。

ちなみにプロファイルにIAMロールを設定できるのは GRC の機能ではなく AWSCLI の機能です。
またIAMロールを使っているため当然ですがクロスアカウントアクセスも可能です。

## 設定
```.aws/credentials
[hoge]
aws_access_key_id = dummy
aws_secret_access_key = dummy
```

```.aws/config
[profile codecommit]
role_arn = ${IAM_ROLE_ARN}
source_profile = hoge
role_session_name = ${USER_NAME}
```

## 使い方
REGION と PROFILE_NAME は省略可能です。

```
git clone codecommit::${REGION}://${PROFILE_NAME}@${REPOSITORY_NAME}
```
```
git clone codecommit::ap-northeast-1://codecommit@fuga_repo
```

# 注意点

このやり方は次のような場合には向きません。（多くのケースでは問題ないとは思います）

- アクセスするAWSアカウントが非常に多く、またリポジトリ名が重複している
- 別の開発チームのリポジトリを利用、かつ submodule にしている
    - サブモジュールへのアクセスは登録されているURLで行われます
    - サブモジュールが CodeCommit の Git 認証の場合にはその対応が必要です

# 所感

Git認証情報を管理しなくてよくなるのは気分的に楽です。

あとIAMユーザーを利用して管理コンソールからCodeCommitを操作しない場合にはIAMロールの料金だけになります。AWS Organizations では5ユーザーの無料枠は実質ないので、今回の方法でCodeCommitの固定料金を少しだけ削減することが可能です。

# 参考
https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-git-remote-codecommit.html

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-role.html

https://qiita.com/rtkym/items/df6a4262a23d5969f9a8
バウンダリ 【boundary】 バウンダリー

バウンダリとは、境界、限界、限度などの意味を持つ英単語。IT分野では、記憶領域を同じ長さごとに分割した境界や、機器やシステム、ネットワークなどが外部と接する境目などのことをこのように呼ぶ。
multipart/form-data(マルチパートフォームデータ)

multipart/form-dataとは、電子メールの添付ファイルやHTTP通信でファイルの種別を表すのに用いられるMIMEタイプの一つで、HTMLフォームによるデータ送信を意味するもの。WebブラウザからWebサーバへのファイルのアップロードなどに用いられる。
スタックトレース

スタックトレースとは、プログラムの実行過程を記録したスタックフレームを記録しておくことである。 スタックフレームは、関数が呼ばれるために生成される。 その内容はシステムやコンパイラなどの実装によって異なるが、呼び出し元への戻りアドレスやローカル変数などによって構成されている。
【Rails】ransackで検索機能を作っていく

railsで検索機能をどうやって作ればいいんだろう？
そう思った僕はgemを使ってその機能を実現することにした。

そこで調べてたどり着いたのがransackと言われるgemだ。
使ってみた感想は「最高！簡単な割にちゃんと検索できる」という感じだ。

そこで、ransackのやり方を備忘録として残しておく...

## この記事の対象者
- ransackを使って検索機能を追加したい
- 検索機能のgemを知りたい

## ransackを導入する4STEP
### 1. まずはransackをインストール
```ruby:Gemfile
gem 'ransack'
```

### 2. 次にコントローラーを編集する
postsコントローラーのindexを例とするが、人によってはbooksなり、articlesなりするだろうがカスタマイズしていってほしい。

まずは元のコントローラー
```ruby:posts_controller.rb
class PostsController < ApplicationController
    ...

    def index
        @posts = Post.all.includes(:user).order("created_at desc")
    end

    ...
end
```
そして、変更後のコントローラー

```ruby:posts_controller.rb
class PostsController < ApplicationController
    ...

    def index
        @q = Post.ransack(params[:q])
        @posts = @q.result.includes(:user).order("created_at desc")
    end

    ...
end
```
この@qを使うというのがポイントになってくるわけですね。（おそらくquestionの略でしょう）

### 3. 検索フォームを作成する
```ruby:posts/index.html.erb
<%= search_form_for @q do |f| %>
    <%= f.label :(カラム名)_cont, "投稿検索" %>
    <%= f.search_field :(カラム名)_cont, class: 'form-control', placeholder: '検索ワード' %>
    
    <%= f.submit "検索", class: "btn btn-primary"%>
<% end %>
```
(カラム名)の中にはtitleやcontentなど検索に使いたいカラム名を入力してください。

_contというのは部分一致で１文字でもあっていたら、表示という感じです。そこら辺は公式ページを見た方が確実ですね（英語ですが...）↓

https://activerecord-hackery.github.io/ransack/getting-started/search-matches/

### 4. has_manyを使っているなら(必要な人だけフェーズ）
include(:user)を使っているからなのか、has_manyを使っているからなのか、僕はエラーが出ました。エラー通りにコードを書けばいいのですが、一応共有しておきます。
```ruby:models/post.rb
# 以下の2つのメソッドがないと検索ができなくなる
  def self.ransackable_attributes(auth_object = nil)
    ["content", "created_at", "id", "title", "updated_at", "user_id"]
  end

  def self.ransackable_associations(auth_object = nil)
    ["comments", "likes", "user"]
  end
```
僕はpostsテーブルのカラム名と、外部キー制約で繋いでいるテーブル名を書かないとエラーになりましたが、皆さんはエラーメッセージ通りに書けばいいと思います。

## まとめ
いかがでしたか？簡単でしたね。さすがgemって感じですよね。
この記事が皆さんの役に立てば嬉しいです！！

参考にした記事を紹介します

ransackで検索機能をつける基本のキ↓

https://qiita.com/mmaumtjgj/items/8731a70b3f328770867c

公式ページ（英語ですが、翻訳しながら読めばわかりますよ）↓

https://activerecord-hackery.github.io/ransack/getting-started/simple-mode/
WSLのUbuntu上でDockerイメージをビルドしてAzure Container Registryにプッシュする

船井総研デジタルの@fsd-takizawaです。
毎回、手順を忘れてしまうので、自身の備忘のために本記事を作成しています。

# 前提
Dockerファイルは作成済みとする。

# 手順サマリ
1. Dockerイメージを作成
1. コンテナのテスト起動
1. イメージをACR向けに作成
1. WSL（Ubuntu）でAzureにログイン
1. Azure Container Registry (ACR) へログイン
1. イメージをACRへプッシュ

# 手順詳細

## Dockerイメージのビルド

```bash
docker buildx build -t <イメージ名[1]>:<タグ[1]>
# 例
# docker buildx build -t sample-image:v1
```

## コンテナのテスト起動
```docker run```コマンドでテスト起動して稼働を確認する

## イメージをACR向けに作成
```bash
docker tag <イメージ名[1]>:<タグ[1]> <ACRのログインサーバー>/<イメージ名[2]>:<tag[2]>
# 例
# docker tag sample-image:v1 acrname.azurecr.io/push-image:v2
```
ここで```acrname.azurecr.io```の```acrname```はACRリソース名となる

## Azureへログイン
```bash
az login --use-device-code
```
その後は表示されるメッセージに従う

## ACRへのログイン

### 権限付与
Azure portal上で
1. ACRの```アクセスキー```で __管理者ユーザー__ を有効化する
1. IAMでユーザーに以下の権限を付与（付与権限は適切に行う）
    - AcrPull
    - AcrPush

### ログイン
```bash
az acr login --name <ACRリソース名>
```

## イメージのACRへのプッシュ
```bash
docker push <ACRのログインサーバー>/<イメージ名[2]>:<tag[2]>
# 例
# docker push acrname.azurecr.io/push-image:v2
```

以上です。
Azure Prompt Flow の躓きメモ

### はじめに

[過去の記事](https://qiita.com/fsdg-honda/items/ed2a70be8b3c8a441a00)で Azure Prompt Flow を使って RAG を評価する手順を記載しましたが、評価する際にいくつか躓きポイントがあったので、Azure Prompt Flow 側への要望込みでご紹介したいと思います。

:::note warn
Azure Prompt Flow は 2023/10/27 時点でプレビュー段階にあり、今回ご紹介する内容も今後改善される可能性があります（改善されることを期待しています）。
:::

### 一括テストの進捗状況がわからない

一括テスト（Batch run & Evaluate）で多数のテスト項目を実行中、進捗状況が知りたい場合があると思いますが、Overview 画面には表示されません。フローや Jobs の一覧の ＿pf＿.lines.completed など、実施済の項目数が表示される箇所はあるのですが、実行中には表示されないようです。
Overview 画面ですぐ確認できると便利と思います。

私の場合は、フローの Details ボタンから遷移した先にある Logs タブで進捗を確認していました。
ログを確認すると
```
[Lines] [Finished: 実施済件数] [Processing: 処理中件数] [Pending: 未実施件数]
```
の形式でログ出力されている箇所があります。
どの項目を実行中かも次行に表示されるので、長時間完了していないテストがないかを確認することもできます。

![スクリーンショット 2023-10-27 184624.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/d3519bfc-c730-a096-5db8-60068c8f7654.png)

### モデルのクォータ制限でエラーが頻発する

前述のログにも`Active threads: 16 / 16`といったログが出力されていますが、私が利用した環境では、16 スレッドでテストが並列処理されているようです。  
フローで Azure OpenAI Service のモデルを利用している場合、クォータ制限によってモデルの呼び出しでエラーが頻発する事象が発生しました。
私の場合はリトライとウェイトを設けることで回避しましたが、並列度数も制御できた方が調整がしやすいように思います。

### 評価結果を一括エクスポートできない

各テスト項目の出力と評価結果を確認する場合、Details 画面の Outputs タブからエクスポートが可能なのですが、これが下記の 2 択となっています。

1. Download current page
2. Download data export script

![スクリーンショット 2023-10-27 190552.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3104149/c4b1445c-eb89-fff0-9f1a-0216edf6a05f.png)

前者は CSV でエクスポートできるのですが、表示しているページ単位でしかエクスポートできません。1 ページあたりの項目数は 25 個で固定となっているため、項目数が多いと非常に手間がかかります。
後者は全ての項目をエクスポートできますが、script（Python）でダウンロードした後でこれを実行する必要があります。また、Windows で実行する際は、encoding を指定しないとエラーとなるようです。

```python
with open(csv_path, "w", newline="", encoding="UTF-8") as csv_file:
```

ワンクリックで全項目をエクスポートできるようにしていただきたいところです。

### 最後に

細かい改善要望を記載していますが、リリース当初から UI も改善されてきており、便利になってきていると感じています。最後の一括エクスポートについても、リリース当初は「Download current page」の機能しかなく、一括エクスポートができたことでかなり手間は削減されました。
今後の改善に期待しています。
【Rails】Devise(ユーザー認証）の使い方を解説していく

gemの使い方などで漁っていたら、どうやらdeviseでユーザ認証ができるらしい。
いやいや、どうせ難しいんでしょう？

そう思っていたのだが、まぁ簡単（基本的な部分はですが...）
ということで今回はdeviseの使い方を解説していきます。

## この記事の対象者
- deviseというgemを使ってログイン機能を追加したい
- 簡単にログイン機能を追加したい
- cancancanなどのgemを使いたい

## deviseの使い方4STEP（最低限動くようにする）

### 1. まずはdeviseのgemをインストールする
```ruby:Gemfile
gem 'devise'
```
```bash:ターミナル
bundle install
```

### 2. ターミナルで以下のコマンドを実行します。
```bash:ターミナル
rails g devise:install
```

### 3. rootパスを用意してください。routes.rbファイルに
```ruby:routes.rb
root "homes#index"
```
とでも書いて、コントローラとビューを用意すればOKだと思います。

### 4. 以下のコマンドを実行し、モデルを作成してデータベースを作成します。
```bash:ターミナル
rails g devise user
```

はい、お疲れ様です。これで最低限のユーザ認証はできるようになりましたよ👍
試しに以下のコマンドを実行してみてください。
```bash:ターミナル
rails routes
```

そうすれば、自分で設定していないにも関わらずsign_inなどのパスがあるはずです。
一応解説しておくとそれはconfig/routes.rbファイルの中の
```ruby:routes.rb
devise_for :users
```
という1行のおかげです。

## まとめ
「おいおい、簡潔に書きすぎちゃう？もっとカスタマイズなり教えろし」
と思ったことでしょう。

その通りです笑

いろんなカスタマイズ方は他の記事でたくさん解説されていますし、そちらをみた方がわかりやすいかと...

以下は参考になった記事を一つづつ載せておきます（実際に手を動かしながら学んだ方がいいですよ！！）

基本のキはこれ↓

https://pikawaka.com/rails/devise#devise%E3%82%92%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%8C%96%E3%81%97%E3%82%88%E3%81%86

カスタマイズして使う方法（全３シリーズ）↓

https://qiita.com/ysk91_engineer/items/108e8d451aa33333e248

こちらもめちゃめちゃわかりやすくまとまってておすすめ↓

https://plog.kobacchi.com/rails7-devise-finally-responded-to-turbo/#index_id0

https://plog.kobacchi.com/rails-devise-user-profile-customize/#index_id1

以下は理論が豊富なので、上級になりたいなら読むべし↓

https://techracho.bpsinc.jp/hachi8833/2023_09_01/133452
テンプレートリテラルを押し付けて実行する関数

## テンプレートリテラル
テンプレートリテラルはJavaScriptにおける文字列の表現方法の1つです。バッククォート(`` ` ``)を用いて`` `hello` ``のように式を記述します。
テンプレートリテラルは記述中に異なる式を埋め込めることが特徴的です。ドル`$`と波括弧`{}`を用いて式を埋め込みます。
```js
const familyName = 'Einstein';
const givenName = 'Albert';

// Albert Einstein
const fullName = `${givenName} ${familyNmae}`
```
上記の例ではテンプレートリテラルを用いて`familyName`と`givenName`を埋め込んだ文字列`fullName`を生成しています。

## タグ付きテンプレート
テンプレートリテラルは稀に下記のように利用されることがあります。
```js
tag`${givenName} ${familyNmae}`
```
`tag`という関数に対してテンプレートリテラルを押し付けるような形です。
Next.jsの利用例としてServer Actions内でSQLを呼ぶ例が執筆当時では話題となっていて、そこでも`@vercel/postgres`の`sql`関数でタグ付きテンプレートを利用しています(話題となっている理由は別のところですが)。
```js
sql`SELECT * FROM posts WHERE likes > ${likes};`
```

これはテンプレートリテラルのより高度な形式でタグ付きテンプレートと呼ばれます。この形式におけるタグとは`tag`や`sql`のようなテンプレートリテラル前の関数を指しています。
関数では押し付けられたテンプレートリテラルについて詳細な情報を引数から扱えます。
```js
const analysisTemplateLiterals = (
  strings,
  ...keys
) => {
  console.log(strings);
  console.log(keys);
};
// ['', ' ', '', raw: Array(3)]
// ['Albert', 'Einstein']
analysisTemplateLiterals`${givenName} ${familyNmae}`;
```
上記の関数で入力を確認すると、第1引数はテンプレートリテラルの埋め込み単位で分割した文字列が配列で渡されます(`raw: Array(3)`については後述)。第2引数以降は残余引数として埋め込んだ式が渡されます。

これらを利用してHTMLエスケープする便利な関数`escapeHtml`を作成できます(ここで作成する関数が完全にHTMLエスケープすることは保証しません)。
```js
const escapeHtml = (
  strings,
  ...keys
) => {
  const escapedValues = keys.map(key => {
    return String(key)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  });
  let result = '';
  for (let i = 0; i < strings.length; i++) {
    result += strings[i];
    if (i < escapedValues.length) {
      result += escapedValues[i];
    }
  }
  return result;
};
```
ユーザの入力を元にした値をこれを利用することによって`` escapeHtml`Hello ${userInput}!` `` 簡単にHTMLエスケープした文字列として扱えます。

話は戻ってタグが受け取る第1引数にあった`raw: Array(3)`について注目します。
以下のように`raw`の部分と比較するようにタグを記述して動作を見ます。
```js
const analysisRaw = (strings) => {
  console.log(strings);
  console.log(strings.raw);
};

analysisRaw`Good Morning\nGood Evening`
// ['Good Morning\nGood Evening', raw: Array(1)]
// ['Good Morning\\nGood Evening']

const analysisRawFirst = (strings) => {
  console.log(strings[0]);
  console.log(strings.raw[0]);
};

analysisRawFirst`Good Morning\nGood Evening`
// Good Morning
// Good Evening
// Good Morning\nGood Evening
```
`console`では`\n`による改行がされていない元の文字列が出力されました。`raw`はこのようにテンプレートリテラルが入力された時の文字列をそのまま持つ配列で、第一引数の配列に対応してそれぞれ格納されています。

このように第1引数は`string`の配列以外にも`raw`を持つのでTypeScriptでは`TemplateStringsArray`として実装されています。
```ts
interface TemplateStringsArray extends ReadonlyArray<string> {
  readonly raw: readonly string[];
}
```

## さいごに
この記事ではタグ付きテンプレートについて紹介しました。知っていない時にこの表現を見ると理解し難い式ですが、知っていると綺麗にハマるケースも多いので活用できるようになりたいです。
はじめて読む486　第8章 タスク 

## 8. タスク

## 8.1 タスク機能

- タスクとは、独立した資源を保持するプログラムの実行単位
- オペレーティングシステムによっては、タスクの代わりにプロセスということもある
- マルチタスクを実現するために、メモリの確保、タスクの起動や終了、タスクの切り替え、タスク管理情報の操作などの仕事をするのがオペレーティングシステムの役割
- 486のタスク機能
    - タスク切り替え機能
    - メモリ空間の分離保護機能
- スレッドは、資源を共有する実行単位で、同じメモリ空間の中で複数の処理を並列に実行する仕組み
    - スレッドの切り替えは、実行するアドレスやスタックなど、ごくわずかの資源を切り替えれば良いので、高速に処理できる
    - スレッドの切り替えには486のタスク機能は重すぎるので、オペレーティングシステム内の小さなプログラムによって切り替える
- タスク切り替えが発生すると、切り替えの瞬間に、実行状態とCPU内のレジスタの内容をメモリに保存し、メモリに保存してあった切り替え先のタスクの実行状態をレジスタに読み込む
- TSS（Task State Segment）
    - 486は、タスク状態の保存・復元に使用するデータ領域の構造をTSSという形式で規定している
    - TSSはタスク1つにつき必ず1つ用意する
    - タスク切り替え処理は、486がCPU内の状態の保存と復元を担当し、オペレーティングシステムはそれ以外のタスク状態の管理を担当する
    - TSSは、レジスタ保存部、オペレーティングシステム用タスク管理情報部、I/O許可マップの3つの部分に分けられている
        - レジスタ保存部は486が使用する
        - タスクに資源を割り当てたり資源の状態が変化した場合には、オペレーティングシステムは、オペレーティングシステム用タスク管理部にその内容を記録していく
        - I/O許可マップは保護機能に関する部分で、TSSにI/O許可マップがない場合は、そのタスクはI/Oポートにアクセスすることはできない
- TSSディスクリプタ
    - TSSのアドレスやサイズを記述するディスクリプタ
    - タスクを起動するたびにTSSとTSSディスクリプタが1つずつ増えていく
- タスク切り替えを実行する命令は、セグメント間ジャンプ命令で、486はジャンプ先がTSSであることを検出するとジャンプの代わりにタスク切り替えを実行する
- タスク切り替えはセグメント間コール命令でも行うことができる
    - ジャンプ命令：タスクを順繰りに切り替えていく場合に使用
    - コール命令：タスクを切り替えて処理を実行後、また元のタスクに戻るような場合に使用
    - セグメント間コール命令でタスクを切り替えると、486はEFLAGSレジスタのNT（Nested Task）をヒットし、切り替え後のタスクが使用するTSSのバックリンク領域に元のタスクのセレクタ値を保存する
    - ジャンプ命令では切り替え後のタスクのTSSディスクリプタの属性をビジーTSSに変更し、切り替え前のタスクのTSSディスクリプタの属性を通常に戻すが、コール命令の場合はビジーTSSのままとなり、タスク切り替えのループはできない（ビジーTSSとされたタスクに切り替えようとすると一般保護例外が発生する）
    - EFLAGSレジスタのNTビットがセットされている場合は、IRET命令は元のタスクに戻る命令として働く
    - IRET命令はTSSのバックリンク領域から取り出したセレクタ値の指すタスクへ切り替えを行い、EFLAGSレジスタのNTビットを0にクリアし、TSSディスクリプタをビジーTSSから通常のTSSに戻す
- TR（Task Register）
    - 現在のTSSを常に保持している16ビットのレジスタ
    - タスク切り替えを実行するとき、TRの指すTSSに現在のタスク状態を保持し、切り替え後のTSSからタスク状態を読み出し、そのTSSのセレクタ値をTRに格納する
    - 原則、オペレーティングシステムがTRを参照することはないが、オペレーティングシステム起動直後のみ、最初のタスク切り替えの時にタスク状態を保存するTSSのセレクタ値をTRに設定しておく必要がある
- タスクゲート
    - アプリケーションソフトウェアによるタスク切り替えを原則禁止にしながらも、一部を条件付きで許可するための仕組み
    - タスクゲートを指すセレクタ値を指定したセグメント間ジャンプ命令によって、タスク切り替えを実行することができる
    - CPUの特権レベル（CPL）がタスクゲートの特権レベルに比べて同じか高い状態であれば命令を実行できる
        - TSSを指すセレクタ値を指定したセグメント間ジャンプやコール命令によるタスク切り替えでは、486がTSSの特権レベルをチェックして、現在の動作レベルよりもTSSの特権レベルが高いと、一般保護例外が発生する
        - TSSの特権レベルが0であっても、そのTSSを指すタスクゲートの特権レベルが3であれば、動作レベル3のアプリケーションソフトウェアでもタスク切り替えを実行できる
    - タスクゲートは割り込みディスクリプタテーブルにも作成できる
        - 割り込みによるタスク切り替えでは、セグメント間コール命令の場合と同じ処理が行われる
- 割り込みや フォールトの発生によって割り込みゲートやトラップゲートが呼び出される場合には、それだけではタスクは切り替わらない点に注意
    - 同じタスクの中で割り込み処理ルーチンのプログラムが実行される
- タスクと特権レベルは独立した概念なので切り離して考える
- アプリケーションソフトウェアの保持する資源はタスクごとに独立しているが、オペレーティングシステムが持つ資源は全タスクについて共通している
    - オペレーティングシステムそのものは1つしか存在しないので、複数のタスクの実行単位が、それぞれ同じプログラムを実行する
    - 1つのプログラムに対し、実行途中の状態がタスクの数だけ存在する
EC2インスタンス内にApacheサーバーを作成

環境
OS：Amazon Linux 2023

まずはパッケージを更新。
```shell
dnf install
```
一覧を確認後にy 
最初からオプション -y でインストールでも可
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/4c4857a9-d21a-4f52-ab32-fdb496c6f656.png)

httpdをインストール
```shell
dnf install httpd
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/4b6b6597-c8ca-79c1-9849-b6cb6932a8d4.png)

htmlディレクトリへ移動
```shell
cd /var/www/html
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/0c1a0ce2-57f2-fdda-42d7-1cdd0eb275f1.png)
HTMLファイルを作成するためにnanoエディターを起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/4bcd7158-f0bd-3e86-72af-acd0b58be889.png)
```shell
nano index.html
```
以下を入力
```shell
<html><h1>hallo world!</h1><html>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/938d9b5c-5fa9-6f43-93e2-471aecdf2a41.png)
Ctrl+X y Enterで保存
次に、Apacheを起動する
```shell
systemctl start httpd
```
自動で起動するようにする
```shell
systemctl enable httpd
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3312479/da81310d-0e7a-622d-55c1-715a91ca4132.png)

Webページが作成できたか確認する
EC2インスタンスのパブリックIPをコピーしてWebでアクセス。
表示されたら成功。
表示されず、読み込みが続いている場合は、セキュリティグループでhttpが許可されていない可能性がある。
OpenAI APIとPythonを使ってChatBOTをサクッと作りましょう！

OpenAIのAPIとPythonで簡単なChatBOTを作ってみましょう。
とりあえずはコードをコピペでもokです。
Secret keyだけは取得していくださいね。それでは行ってみましょう！

# コード

    import openai
    
    openai.api_key = "secret key"
    
    def chat_with_gpt(prompt):
        response = openai.ChatCompletion.create(
            model = "gpt-3.5-turbo",
            messages=[{"role": "user", "content": prompt}]
        )
    
        return response.choices[0].message.content.strip()
    
    if __name__ == "__main__":
        while True:
            user_input = input("You: ")
            if user_input.lower() in ["quit", "exit", "bye"]:
                break 
    
            response = chat_with_gpt(user_input)
            print("Chatbot: ", response)
            

以上です😁

# 実行

次にpython main.pyを実行するとYou:　と表示されるので「Hi」でも「Hello」でもいいので話しかけてください。


# コードを詳しく説明
コードについてもっと詳しく説明。

## OpenAIライブラリのインポート
    
    import openai

copy
ここでOpenAIライブラリがインポートされています。これはOpenAI APIにインターフェースを提供するPythonクライアントです。

## APIキーの設定

    openai.api_key = "secret key"

この行は、プログラムをOpenAIのサーバーに認証するために必要なAPIキーを設定しています。"secret key"を実際のAPIキーに置き換えてください。

## 関数の定義

    def chat_with_gpt(prompt):


`chat_with_gpt`という名前の関数を定義して、単一の引数`prompt`を取ります。

## 関数の中身

    response = openai.ChatCompletion.create(
        model = "gpt-3.5-turbo",
        messages=[{"role": "user", "content": prompt}]
    )


関数内で、`openai.ChatCompletion.create()`メソッドが呼び出されて、GPT-3.5 Turboモデルと対話します。`model`パラメータは使用するモデルを指定し、`messages`パラメータは会話を模倣するメッセージオブジェクトの配列です。

    return response.choices[0].message.content.strip()


最後に、関数はレスポンスの内容を返します。これはAPIのレスポンスオブジェクトから抽出され、先頭/末尾の空白は削除されます。

## メインプログラムのループ

    if __name__ == "__main__":
        while True:

スクリプトは、スタンドアロンのファイルとして実行される場合、無限ループに入ります。

## ユーザー入力

        user_input = input("You: ")


この行は、コンソールを通じてユーザーからの入力を収集します。

## 終了条件

        if user_input.lower() in ["quit", "exit", "bye"]:
            break


ユーザーが"quit"、"exit"、"bye"のいずれかを（大文字小文字を問わず）入力した場合、ループが終了し、プログラムも終了します。

## 関数呼び出しと出力

        response = chat_with_gpt(user_input)
        print("Chatbot: ", response)

ユーザーの入力は`chat_with_gpt()`関数に渡され、返されたレスポンスが出力されます。

# まとめ

コピペして、シークレットキーを取得して、実行するだけでChatBOTが完成です。簡単ですね。
プログラミングの練習をしたい方はコピペじゃなくてコードを書きながら、ひとつひとつのコードの意味を考えてみてくださいね。勉強になりますよ。
それでは、また、次回、何か作ります。
簡易SNS,BNeTをリリースしました。

23/10　に、[BNeT](http://bnet.ie-t.net)というSNSサービスを公開しました。
## きっかけ
Twitter(現X)が有料化する、という趣旨の報道を受け、対抗として制作しました。
他のSNSにはない機能を色々追加しています。
逆に、ほかのSNSにある機能がなかったりします。
ぜひ、アカウント登録をよろしくお願いします。
## 機能一覧
- 画像アップローダー
- 自動リンク化...等
Amazon Linux 2023について

## Amazon Linux 2023について

EC2を作成・起動したがTeraTermでSSH接続できなかったので調べた結果。

Amazon Linux 2 ではRSAキーペアでSSH接続していましたが
Amazon Linux 2023 ではED25519でなければSSH接続ができないようでした。

さらに、シェルがyumからdnfに変更されており、パッケージアップデートのコマンドなどが少し変わっていた。

yum update -yではなく

```ruby:qiita.rb
dnf install -y
```
で行う必要がありました。

そのうちRSAからED25519にキーペアを変更する記事も書きたいな～と。
・ユーザーデータにテンプレ保存してからインスタンスのkeyファイルの内部を書き換えればいけるのか。
・そもそもssh keygen -tコマンドで作成してアタッチしなおせばいけるのか....