OmniAICreator/Qiita-1.07M huggingface dataset:
pythonを利用したdynamoDBからのレコード取得（1MB以上のレコード数）

# はじめに
DynamoDBから大量にレコードを取得することに困ったので、備忘録

# 一度に取得できるデータ量について

一度に取得できるデータ量は1MBまでと決まっているので、それを超える量のデータは1度では取得しきれずに、複数回データを取得することが必要である。


## 複数回データを取得する方法

前回までのレコード取得でどこまでを取得しているかを引数に渡す必要がある。
全レコード取得できていないときには、responseに「LastEvaluatedKey」というキーを持っている。
そのキーを引数に入れて再度DBにアクセスすることで、続きからデータを取得することができる。
全件取得するためには、LastEvaluatedKeyが帰ってこなくなるまで、無限ループさせてやれば良い。

```python
import boto3
from boto3.dynamodb.conditions import Key

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('TABLE_NAME')

response = table.query(
　　　　　　　　KeyConditionExpression　=　Key('pk').eq('XXX'),
)
# 下記のwhile内で取得したレコードを連結するための箱（data）の準備
data = response['Items']

# レスポンスに LastEvaluatedKey が含まれなくなるまで無限ループ
while 'LastEvaluatedKey' in response:
    response = table.query(
　　　　　　　　    KeyConditionExpression　=　Key('pk').eq('XXX'),
        ExclusiveStartKey=response['LastEvaluatedKey']
    )
    # dataにレコードを追加
    data.extend(response['Items'])
```
pythonを利用したdynamoDBの操作(GSI)

# はじめに
最初に設定したプライマリーキーでは、レコードの検索がうまく行かなかったので、GSIを使ってみた

# 目次
- GSIについて
- GSI利用時のDB探索の書き方


# GSIについて
パーティションキーやソートキーをプライマリーキー以外の組み合わせで追加することができるもの。
よくある例を出すと、IDをプライマリーキーとしておくと、IDでのみしか検索ができないが、GSIでパーティションキー、ソートキーをID以外のキーに貼っておくことで、ID以外のキーで検索することが可能となる。

# GSI利用時のDB探索の書き方
## GSIの貼り方
マネジメントコンソールで目的のテーブルを選択し、インデックスタブを開く。
インデックスの作成をクリックし、目的のキーをパーティションキー、ソートキーに設定する。
※注意点とし、パーティションキー、ソートキーに設定できるのは、文字列、数値、バイナリの3種類の型のみである。ブーリアンとかはNG。

## GSIを利用するpython書き方
GSIでデータを引くときには、引数にIndexNameを追加するだけでOK。
テーブルにpkというキー、skというキーがあったとする。
それらのキーをそれぞれパーティションキー、ソートキーとしたpk-sk-indexという名前のGSIを作ると下記のように記載できる。

```python
import boto3
from boto3.dynamodb.conditions import Key

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('TABLE_NAME')

response = table.query(
　　　　　　　　IndexName　=　'pk-sk-index',
　　　　　　　　KeyConditionExpression　=　Key('pk').eq('XXX') & Key('sk').eq('YYY')
)
```
クロスリージョンのリードレプリカを作成に関するとある実験~Amazon Aurora~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/ad04a3cd-91cc-e381-19dd-450cc041d984.png)
※リードレプリカとリーダーインスタンスは同じです
※最初の画像はRDS(Aurora以外）の構成図であってAmazon Auroraの構成図ではありません。→ここでハマった

【まとめ】
- クロスリージョン系
・「クロスリージョンのリードレプリカの作成」で作成されたリードレプリカの正体はクラスターである（→一番気づくのに苦労した）
→ 要はクラスター内のリードレプリカやライターインスタンスがスタンドアロンに昇格するのは無理なのである。無理なのである！！！！
・リードレプリカ作成先のリージョンのクラスターは作成元のデータベースと同期される
・リードレプリカ作成先のリージョンのクラスターを昇格させると元のクラスターのデータベースと同期されなくなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/96019d9c-f89f-a2ad-80eb-c9d96dbab631.png)

・クロスリージョンレプリケーションで同じリージョンにもう一度作成するとそのクラスターは削除される。
※イベントでこのように表示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/db7dff4a-d9ff-9bcb-79d9-bf49e2eed042.png)

・クロスリージョン先のクラスタのインスタンスを削除するためにはクラスターを昇格させてスタンドアロンにする必要がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/39c8dffa-cc14-458f-7b54-3b1461d19133.png)

```
Cannot delete the last instance of the read replica DB cluster. Promote the DB cluster to a standalone DB cluster in order to delete it. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidDBClusterStateFault; Request ID: 00c6a147-4621-47c3-b4dc-ba2d70f4e653; Proxy: null)
```

- 非クロスリージョン系
・「フェイルオーバー」はライターインスタンスに対して行われるとリードレプリカのどれかが昇格
・「フェイルオーバー」はリードレプリカに対して行われると現在のライターインスタンスがリードレプリカになる
・ライターインスタンスが削除されるとリーダーインスタンスは勝手にライターインスタンスとしてフェイルオーバーされる

# 実験

auroraのリードレプリカをスタンドアロンに昇格させたときに細かい挙動がよくわからなかったので試そうとしてみました

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Replication.CrossRegion.html#:~:text=Aurora%20MySQL%20%E3%83%AA%E3%83%BC%E3%83%89%E3%83%AC%E3%83%97%E3%83%AA%E3%82%AB%E3%82%92-,%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%89%E3%82%A2%E3%83%AD%E3%83%B3,-%E3%81%AE%20DB%20%E3%82%AF%E3%83%A9%E3%82%B9

クロスリージョンのリードレプリカを作成する前に何を準備する？
基本的に準備はレプリカ作成先のリージョンで行います
･サブネットグループ(そのためにVPCやサブネット等を作成しておく)
※レプリカ作成前のクラスタでVPC内部に設定していてもレプリカ作成時にパブリック変更可能です｡その際にはVPCの設定でDNSホストやDNS解決を有効にしておく必要があります｡
･セキュリティグループ(接続することも考慮して3306のポートの空いたセキュリティグループを作成しておきます)
･パラメータグループは必要ありません｡残念ながらレプリケーション作成時にパラメータグループを指定することができず､もともとカスタムでパラメータグループを設定していてもレプリケーション先ではデフォルトのパラメータグループに戻ってしまいます･･･

クロスリージョンのリードレプリカを作成すると何が起こる？
･それぞれのリージョンでマスターおよびクラスタがある状態になる
→要はリードレプリカ作成先でマスターインスタンスが作成される｡
→これらは同期される(もとのDBで書き込みを行えばもう片方のリージョンのデータベースが更新される)

では次にレプリカをスタンドアロンに昇格させようと思います

手順
----------------------------------------

プライマリ DB インスタンスに対するトランザクションの書き込みを停止し、すべての更新がリードレプリカに反映されるまで待ちます。
※Replica Lag メトリクスを使用して、リードレプリカに対するすべての更新の時期を確認できます。

MySQL および MariaDB の場合のみ、MySQL または MariaDB リードレプリカに変更を加えるには、リードレプリカの DB パラメータグループで read_only パラメータを 0 に設定する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/ba379f69-40eb-d59f-5989-d329a4397991.png)

Amazon RDS コンソールの [昇格] を使用して、リードレプリカを昇格させます。

--------------

うーんなるほど
んでやってみますと・・・
見た目が何も変わっていない・・・どういうこと？

【変わったところ】
ソースのデータベース（クロスリージョン元のクラスター）のデータが同期されなくなった。
昇格してクラスタがスタンドアロンになる前はデータが同期されていた。

そうなんだけどさ。。。リードレプリカの昇格がクロスリージョン先のクラスターを指しているってなんか混乱させる表現だな。。。解釈が間違ってるのか・・・
とにかくクロスリージョンのリードレプリカの作成で作成されるのはクラスターだから！！！！

https://blog.serverworks.co.jp/tech/2019/07/31/how-to-change-aurora-db-instance-class/
ジョイスティックで読み取った直交座標系を極座標系に変換する方法

この記事ではジョイスティックの値からジョイスティックの原点からの距離と角度を求める方法について解説していこうと思います。要は直交座標系から極座標系に変換する方法ということです。<br>ソースコードはmbed用です。また、使用しているジョイスティックはsparkfun社の下記の画像のものです。<br>~~留年に大きく関わるテストで寝坊したような奴なので~~厳密には正しくない表現や文章が文法的に間違ってるところがあるかもしれませんが部活の講習とmarkdown記法の練習のためにこの記事を書いているので許してください><
![sparkfun_ジョイスティック](http://dlnmh9ip6v2uc.cloudfront.net/images/products/10433-01b.jpg) 
#はじめに
ジョイスティックとはスティックを傾けることによって方向入力を行うことができる機器です。<br>sparkfun社のジョイスティックではHORZピンがx軸、VERTピンがy軸、SELピンがスティックの押し込みに対応しています。
また、HORZピンとVERTピンは原点で$\frac{V_{cc}}{2}[V]$,それぞれ矢印方向に傾けると$V_{cc}[V]$,矢印の反対方向に傾けると$0[V]$が連続的に出力されます。
#原点からの距離の計算
まず、次の画像に示すように単位円内部$\Bigl((x^2+y^2<1)の範囲\Bigr)$の任意の点P$(x,y)$を考えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524988/1f1959c7-6254-f97c-f743-6bd99feac7a3.png)
ここで、点Pの原点からの距離$r$は三平方の定理から

```math 
r=\sqrt{x^2+y^2}
```
で求められます。この式の$x,y$にジョイスティックで読み取った値を代入するだけで原点からの距離(ジョイスティックをどれだけ傾けたか)がわかります。<br>ここで、問題点があります。それは、HORZ,VERTピンが[はじめに](#はじめに)で述べたように出力されるため、原点で$(x,y)=(0.5,0.5)$となり単位円と対応しないということです。とりあえず原点で$(x,y)=(0,0)$となるように$x,y$の値をそれぞれ0.5で引くと、原点での問題の解決はしますが、矢印方向,矢印の逆方向に傾けた時の値の絶対値が0.5になってしまいます。なので、この値を2倍すると、単位円の値と対応させることができます。

#x軸正方向とのなす角の計算
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524988/af96ee84-fd58-5561-8d8f-58244be41631.png)
上記の画像に示すように、x軸正方向と単位円内部の点Pとのなす角$θ$を計算していきます。<br>まず、$arctan$関数を用いて計算すると、次式のようにして求められます。

```math
\theta=arctan\Bigl(\frac{y}{x}\Bigr)
```
一見この数式にジョイスティックで読み取った値を代入すれば求められるように感じます。しかし、$arctan$関数の値域からこの数式の値域は($-\frac{\pi}{2}<\theta<\frac{\pi}{2})$であり、この数式では点Pのx座標が負の値である時に$\theta$が180度位相がズレた値が出てきてしまうため不便です。
そこで、$atan2$関数というものを使います。この$atan2$関数が生み出された背景には、前述したような$arctan$関数の使い勝手の悪さがあることもあり、$atan2$関数では$arctan$関数で求めれない、点Pのx座標が負の値や0であるときの角度を求めることができます。詳細は[wikipedia](https://ja.wikipedia.org/wiki/Atan2)に書いてありますが、x座標が負の値の時などの分岐処理をこの関数が勝手にしてくれています。<br>従って

```math 
\theta=atan2(y,x)
```
という計算式でx軸正方向とのなす角を求めることができます。

#終わりに
何か分からないことやこの記事に誤りがあれば連絡してください。
Lambdaで（定期実行）スクレイピングの初期段階の構築をしてみた

# はじめに
AWS Labmdaで、Pythonでスクレイピングするアプリの基礎部分の構築をまとめた
CloudWatchで毎時実行する設定も組み込んだ
※LabmdamCloudWatchは永久無料で使用できるため、お気軽にご利用ください
　　↓詳細はこちら

https://aws.amazon.com/jp/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=tier%23always-free&awsf.Free%20Tier%20Categories=*all

# モジュールのインストール
下記をローカルで(Macの人はターミナルで）1行ずつコマンド実行してください

```
mkdir packages
cd packages
pip install requests -t ./
pip install beautifulsoup4 -t ./
touch lambda_function.py
```

実行すると↓下記のフォルダができます（2022年2月時点）
![スクリーンショット 2022-02-19 0.34.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/21d0bc77-f411-c44f-1d17-4fa2c7a85603.png)

packagesフォルダを.zipで圧縮してください

# Lambda作成
Lambdaのページを開きます

https://ap-northeast-1.console.aws.amazon.com/lambda/home?region=ap-northeast-1#/functions

画面右上の「関数の作成」を押下します
![スクリーンショット 2022-02-19 0.37.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/ebb3a164-2f43-9d04-59bd-1fb751e0f010.png)

「関数名」に好きな名前を設定し、
「ランタイム」に「Python3.9」を選択して
「関数の作成」を押下します
![スクリーンショット 2022-02-19 0.42.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/5ecee40a-d2a7-57d0-bc54-8a3969b57c59.png)

画面真ん中右の「アップロード元」 > 「.zipファイル」を押下します
![スクリーンショット 2022-02-19 0.44.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/3141490f-7c4e-b6a8-583b-1492b4ca65b7.png)

「アップロード」を押下して、前の手順"モジュールのインストール"で作成した.zipファイルを選択して
「保存」を押下します
![スクリーンショット 2022-02-19 0.48.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/0cc6fae2-56e7-5023-8d79-f7341df4e819.png)

実行すると、下記のようにフォルダが増えます
![スクリーンショット 2022-02-19 0.51.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/4d9d8895-7704-1db1-15a4-e0ec6da11062.png)

packages配下の"beautifulsoup4-4xxxx"などのフォルダを1つ上の階層に移動させます
![スクリーンショット 2022-02-19 0.52.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/9dbaa9e3-a15f-34e0-96b2-fe76d73b77bc.png)

packagesフォルダを削除します

初期に作成した.pyファイルが無くなっていたら作成します
![スクリーンショット 2022-02-19 0.52.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/57d86f6a-25ae-a51b-d5ec-9f71bd0843c3.png)
（↑右クリックでメニューを開いた場合）

# 設定
「設定」を押下します
![スクリーンショット 2022-02-19 1.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/29bb7aaa-0db0-55b4-3f86-21cb3fe11c75.png)

「編集」を押下します
![スクリーンショット 2022-02-19 1.08.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/4251d2ae-4a44-5d59-0dbc-932a1b174b02.png)

メモリを"256"GB
タイムアウトを"1"分（ご自由に）
に設定して、「保存」を押下します
![スクリーンショット 2022-02-19 1.08.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/1a51058a-6245-e1b6-cc49-d56aef3cb48f.png)
pythonを利用したDynamoDBからのデータ取得（取得件数の制限）

# はじめに
dynamoDBから取得するレコード数の最大数を指定したかったので、調査した。

# レコード数制限のかけ方

queryなどの引数にLimitを追加するだけでOK。

```python
import boto3
from boto3.dynamodb.conditions import Key

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('TABLE_NAME')

# ここの引数にLimitを入れる
response = table.query(
　　　　　　　　KeyConditionExpression　=　Key('pk').eq('XXX'),
    Limit = 3
)
```
CentOs Failed to get D-Bus connection: Operation not permitte 解決策

docker pull で取得したCentOS環境で systmctl コマンドを実行すると　```Failed to get D-Bus connection: Operation not permitte```というエラーが表示されることがあります。

## 解決方法
systemctlを有効化してcentOSを立ち上げる必要がある。

```
$ docker run -d --privileged  centos /sbin/init
$ docker exec -it [id]  /bin/bash
```

[id]にはコンテナidが入ります。
ReactでscrollRevealを使用する


refとカスタムhookの概念の解像度があがったのでmemoします。


## ScrollRevealとは
JQueryを使用せずアニメーションを付けられるライブラリ。
https://scrollrevealjs.org/


## 1.インストール

HTMLで
```
<script src="https://unpkg.com/scrollreveal"></script>
```
を読み込む。

もしくはnpmでインストール。
```
npm install scrollreveal --save
```
私は後者で進めました。



## 2.メソッド ScrollReveal().reveal('');
アニメーションをつけるには
`ScrollReveal().reveal('');`
のメソッドを使って、HTMLのclassに指定する。
''の中には指定するclass名が入ります。

Vanilla jsで書いてみた↓
<a href="https://codesandbox.io/s/billowing-snowflake-sy2ep3?fontsize=14&hidenavigation=1&theme=dark">
<img alt="Edit sy2ep3" src="https://codesandbox.io/static/img/play-codesandbox.svg">
</a>


## 3.Reactのコンポーネント化
ここが難しくて苦戦しました。refを理解する良い機会になりました。

```ScrollReveal.js
import React, { Component } from "react";
import ScrollReveal from "scrollreveal";
import { useRef, useEffect } from "react";

const Scroll = ({ children }) => {

  const sectionRef = useRef();
  useEffect(() => {
    if (sectionRef.current) {
      ScrollReveal().reveal(sectionRef.current, {
        reset: true,
        delay: 700,
        opacity: 0,
        distance: "40px",
      });
    }
  },[]);

  return (<section ref={sectionRef}>{children}</section>)
}

export{ Scroll }
```
useRefで該当のコンポーネントまでスクロールした時にDOMを参照します。
useEffectを使うことで、対象のDOMが参照されるたびにScrollReveal().revealが実行されます。


```Main.js
import {Scroll} from './ScrollReveal.jsx'

export const Main = () => {
return(
            <Scroll>
            <h1>
              Web designer
              <br />
              Front-end developper
            </h1>
            </Scroll>
```
上記のように<Scroll>でアニメーションを付けたい箇所を囲って完成です。


参考にした記事
https://qiita.com/uwattotaitai/items/5957eda0c63634fbaa56
https://qiita.com/tonio0720/items/c265b9b65db3bb76f2d3
https://zenn.dev/butter67/articles/2020-09-23first-article
クレヨンしんちゃん (Swift)

### Respect for
https://qiita.com/noppefoxwolf/items/b4376392d98cea2446dd

# キャンパスサイズの設定
最近クレヨンしんちゃんを見ていないので念の為4:3にしましょう、自信があれば16:9でも良いと思います。

``` Swift
import UIKit

let shinView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 300))
let title = UILabel()

title.text = "Hello World"
title.frame = CGRect(x: 0, y: 0, width: 400, height: 300)
title.center = shinView.center
```
![スクリーンショット 2022-02-19 0.19.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508617/884e3c19-df04-92b1-a92a-c948c51bbb4b.png)


# 色の定義

``` Swift
let topColor = UIColor(red: 0.94, green: 0.51, blue: 0.64, alpha: 1.0)
let bottomColor = UIColor(red: 0.95, green: 0.95, blue: 0.50, alpha: 1.0)
```
これらの色をCAGradientLayerで描画します。

``` Swift
let gradientLayer: CAGradientLayer = CAGradientLayer()

let topColor = UIColor(red: 0.94, green: 0.51, blue: 0.64, alpha: 1.0)
let bottomColor = UIColor(red: 0.95, green: 0.95, blue: 0.50, alpha: 1.0)
let gradientColors: [CGColor] = [topColor.cgColor, bottomColor.cgColor]

gradientLayer.colors = gradientColors
gradientLayer.frame = shinView.bounds
shinView.layer.insertSublayer(gradientLayer, at: 0)
```
![スクリーンショット 2022-02-18 23.58.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508617/47ff8b50-aa9d-f6b0-6a15-c1af006f7569.png)

やりたいことが分かってきたでしょうか

# タイトルの設定

タイトルを追加します。

``` Swift
let titleColor = UIColor(red: 0.38, green: 0.01, blue: 0.37, alpha: 1.0)
title.text = "開発途中で\n   だいたいプロジェクト頓挫するゾ"
title.numberOfLines = 0
title.font = .boldSystemFont(ofSize: 18)
title.textColor = titleColor
```
numberOfLinesで改行可能にし、~~Paddingはめんどくさいので~~タブ文字を1文字入れて2行目を少しズラします。
![スクリーンショット 2022-02-19 0.34.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508617/0a68d5d3-b78b-bb27-8019-85110f2dfc4d.png)

# ルビをふる
ルビのLabelの位置をAutoLayoutでいい感じに調整します。
![スクリーンショット 2022-02-19 0.49.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508617/04bcad34-a1db-b7d7-1dc3-63adc676f746.png)

ルビの文字色をタイトルと合わせておきます。

``` Swift
let titleColor = UIColor(red: 0.38, green: 0.01, blue: 0.37, alpha: 1.0)
ruby.text = "かいはつとちゅう"
ruby.font = .boldSystemFont(ofSize: 10)
ruby.textColor = titleColor
```
![スクリーンショット 2022-02-19 0.52.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508617/8f7cc917-cb50-6851-a003-b101fd01ae46.png)

これでSwiftでクレヨンしんちゃんのタイトルコールを作ることが出来ました。
いかがでしたか？

# オリジナル
https://qiita.com/noppefoxwolf/items/b4376392d98cea2446dd

# HTML + CSS バージョン
https://qiita.com/yhatt/items/4cd0c21b6bf5cf8af456
[macOS] VSCodeで快適にUnity開発する設定(2022/02/19)

VSCodeで快適にUnity開発するため、いまどき当たり前なコード補完・エラー表示・自動フォーマットの環境を整えたい。

ただ、検索して色々試したが、途中でつまづく手順が多かった。そのため、現時点でうまく行った作業手順をできるだけ漏らさずメモする(2022/02/19時点)。

基本的に以下のドキュメントに従って進め、うまくいかないところを補完する。

- Unity Development with VS Code
    - https://code.visualstudio.com/docs/other/unity

## 確認環境
- MacBook Pro (16-inch 2019)
- macOS Monterey 12.0.1
- Unity 2019.4.33f1 Personal

## 1. 準備

以下をインストールする。

- .NET Core SDKのインストール。ここでは.NET 6.0 LTSをインストールした。-> https://dotnet.microsoft.com/en-us/download
- Mono Stable版をインストール。ここでは6.12.0(Stable Channel)をインストール -> https://www.mono-project.com/download/stable/
- VS Code MarketplaceからC＃拡張機能をインストール。 -> https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp

## 2. UnityとVSCodeを連携

Unityのツールバーから[Unity] - [Preferences] - [External Tools] を選択。[External Script Editor]でVisual Studio Codeを選択しておく。

そして、以下の設定を`settings.json`に書き込むとコード補完・エラー表示が効くようになる。

```json
    "omnisharp.useGlobalMono": "always",
    "omnisharp.monoPath": "/Library/Frameworks/Mono.framework/Versions/Current"
```

うまく機能しない場合は

- VSCodeの再起動
- OmniSharpのReStart(コマンドパレットで「omni」と入れると候補に出てくる)

をしてみるとよい。


- 参考: 
    - vs code Problems with C# extension, Some projects have trouble loading due to OmniSharp
        - https://stackoverflow.com/a/70640179
    - 【vscode/Unity】monoを認識せず、インテリセンスが消えたときの対処法
        - https://zenn.dev/leaf/articles/ee0b7b796b9036

## 3. Unityの警告を有効にする
ここまででC#に関してコード補完・エラー表示が出るようになっているが、Unityのエラーも表示されるようにしたい。

まず、Unityプロジェクトのルートに`omnisharp.json`ファイルを作成し、以下の内容にして保存する。

```json
{
  "RoslynExtensionsOptions": {
    "EnableAnalyzersSupport": true,
    "LocationPaths": ["./NuGet"]
  }
}
```

次に、同じ場所に`NuGet/`ディレクトリを作成する。
そして、下記サイトの右に表示されている「Download package」からパッケージをダウンロードする。

https://www.nuget.org/packages/Microsoft.Unity.Analyzers/

ダウンロードされたファイルを解凍する。

```sh
unzip microsoft.unity.analyzers.1.12.0.nupkg
```

そして、中から`Microsoft.Unity.Analyzers.dll`というファイルを抽出する。確認した時点では、`analyzers/dotnet/cs`にあった。このファイルを`NuGet/`ディレクトリの中へ配置する。

この状況でUnityのエラー表示が機能しているはずなので、テストしてみる。例えば以下のメソッドをプロジェクト内のクラスのどこかに作れば、「The Unity message 'FixedUpdate' is empty. [Assembly-CSharp]csharp(UNT0001)」というUnityの警告が表示される。

```cs
void FixedUpdate() {

}
```

うまく機能しない場合は、前述の通りVSCodeの再起動やOmniSharpのReStartでうまくいくことがある。

## 4. コードを保存時に自動フォーマットする

`settings.json`に以下の設定を書き込めば、コードの保存時に自動フォーマットしてくれる。

```json
    "[csharp]": {
        "editor.formatOnSave": true
    }
```

以上
【Rails】Provideメソッド

# 使い方


:titleに'sample'定義

```erb:sample.html.erb
<% provide(:title, 'sample') %>　
```
<br>
yieldで:titleに定義した'sample'を受け取って描写

```erb:sample_application.html.erb
<title><%= yield(:title) %></title>
```
<br>
<br>

#### 例）ボタンの文字の場合

:button_textに'Button'を定義

```erb:button.html.erb
<% provide(:button_text, 'Button') %>
```

<br>
f.submitでボタン作成、そのボタン上の文字にyield(:button_text)で受け取ったButtonを描写する

```erb:button_application.html.erb
<%= f.submit yield(:button_text), class: "btn" %>
```
<br>
<br>
noindex にすると OGP 画像が表示されない

表題の通りなのですが、ウェブサイトの開発時に OGP を確認したく、[OGP確認](https://rakko.tools/tools/9/)でチェックしたところ、OGP画像が表示されていません。

いろいろ試行錯誤した結果、原因は META 要素の noindex でした。

```
<meta name="robots" content="noindex">
```

開発中なのでクローラーに index されないように仕込んでおいたのですが、これを入れると OGP の画像が読み込まれないようです。
ロリポップでWordPressのサイトを復旧した時SVGが表示されない

WordPressを使ったWebサイトをロリポップで、復旧することになりました。
WordPressの引越しとテーマの反映が容易に終わったので、完成と思いました。

ところが、画像が表示されていないのです。
imagesフォルダのパスが相対パスで書かれていたので、今の環境に合わないのか？と思って修正してもダメでした。

ブラウザの検証機能を使って要素を調べたら、SVGファイルだけが表示されていないと分かりました。

ネットで調べて、この記事を見つけました。

https://hira-s.net/blog/svg/

https://hiromode.hatenablog.com/entry/2018/11/13/153026


ロリポップのようにサーバーにSVGの表示ができるように、設定が必要なサーバーがあるようです。
.htaccessに、MIMEタイプの設定をすると解決します。

```html
AddType image/svg+xml .svg .svgz
AddEncoding gzip .svgz
```
ブログの中には、

```html
AddType image/svg+xml .svg
AddType image/svg+xml .svgz

```
と二つにして書かれている記事もありますが、最初に記載したように、まとめて記載できます。

```html
AddEncoding gzip .svgz
```
このコードは。gzip .svgzで圧縮されているファイルをエンコードできるようにしているそうです。

この設定をしても、表示されないのです。
さらに調べました。

HTMLの画像のタグは、imgとimageの二つがあります。
そして、SVGの画像を扱うときは、imgではなくimageを使うと良いそうです。

https://digiper.com/topics/article/507.shtml

試しにソースの一部を変えて、試してみました。
でも、表示されないのです。
サーバーにアップロードされたHTMLファイルの内容を確認したところ、修正箇所が反映されていないのです。

どこかで、キャッシュが働いているようです。
ネットで調べたところ、この記事を見つけました。
私も、ロリポップのアクセレーターの設定が影響していると思ったのです。
でも、この記事を読みHTMLで修正できることが分かりました。

https://keitai-memo2.info/avalon/2021/03/%E3%83%AD%E3%83%AA%E3%83%9D%E3%83%83%E3%83%97%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AE%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%81%8C%E6%B6%88%E3%81%88%E3%81%AA%E3%81%84/

```html
<meta http-equiv="Cache-Control" content="no-cache">
```
このコードを記載すると良いそうです。

今回重要なコードは、リンク先のページが消えてしまったときに備えて、ここでも掲載しました。

ここまでのことをしても解決しないため更に検索したら、このCSSのソースを見つけました。

http://kz-factory.site/wordpress-svg/

https://www.webprofessional.jp/wordpress-svg/

```CSS
img[src*='.svg']{
    width: 100%;
    height: auto;
}
```

##解決した理由
色々やっても改善されずPHPファイルを見直している中で、念の為imagesのフォルダのパスを絶対パスで書いてみました。
その結果、全ての動画と画像が正常に表示できました。
お騒がせしました。

今回オリジナルの WordPressのテンプレートのCSSの中で、imagesのフォルダのパスを自動で読み取って設定していると思われる箇所がありました。
それが機能していないのは、ロリポップのエコノミープランのせいでPHPがCGI版だからなのかな？と思ってみたりしてます。
CSSは、PHPの扱いと関係ないですが、今回PHPがCGI版というのが気になっています。
とりあえず、本来 WordPressは使えないとされていロリポップのエコノミープランで、WordPressを使っています。
console.logでネストが深くてログが見れない時の対処法

## はじめに

検証ツールのConsoleでconsole.logの結果を見る時は、問題なくログを見れると思います。ですが、出力したいログのネストが深いとターミナルで出力されないケースがあります。


#### 見れませんね...
[Object]と出力されてしまってます。この中身を見れるようにしたいと思います。

![スクリーンショット 2022-02-18 23.38.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396152/412dc7f5-be93-92d5-55b4-87e40a2e7faf.png)

#### ネストが深い場合、出力したいログをJSON形式にしましょう
```
console.log(JSON.stringify('出力したいログ', null, 2))
```

実行結果
![スクリーンショット 2022-02-18 23.38.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396152/50dacd9c-facd-601e-41de-408fb3b6846a.png)

JSON.stringifyの解説をサラッとしたいと思います。第一引数は、JSON 文字列に変換する値です。
第二引数は、replacerです。JSONにする際に、出力内容をフィルターしたりできます。null,undefinedや文字列を渡すと、すべてのオブジェクトのプロパティを出力されます。特にフィルターする必要がなければnullでいいと思いますが、今回は試してみます。

replacerは関数と配列どちらか場合によって指定してください！

```
出力したいプロパティを配列に入れる
const keys = ['type', 'title']
console.log(JSON.stringify('出力したいログ',keys, 2))
```

ログから、answerListというプロパティが消えました。
![スクリーンショット 2022-02-19 0.22.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396152/9c8e58f7-85f3-afc5-bdf9-a7f9c0222a5d.png)

ちなみに、JSON.stringifyの第3引数は、インデントです。お好みで指定してください。

## おまけ
console.logより、console.traceをおすすめしたいです。スタックトレースが表示されているのでどこでログが出力されるか一目でわかります。

![スクリーンショット 2022-02-19 0.26.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396152/162d43a7-8c25-f28f-3b66-bb7421301bb6.png)

```
console.log('=====log=====', log)
```
こんな感じに、ログを書く必要がなくなりますw
venvで仮想環境を構築しようとしたけどactivateファイルができなかったときの対処法

本記事はvenvを使おうとしたときに

`bash: venv/bin/activate: No such file or directory`

というエラーが出た人向けの記事となっております。

### 環境

Linux - Ubuntu 20.04.3 LTS

## 結論

以下のコマンドを実行して、virtualenvで構築する。

```shell
$ pip install --upgrade virtualenv   # virtualenvのアップデート
$ virtualenv -p python3 venv         # 環境名をvenvとして仮想環境構築
$ source venv/bin/activate           # アクティベート
```

## 遭遇したエラー

venvで仮想環境を構築しようと以下のコマンドを実行したところ

```shell
$ python3 -m venv venv
$ source venv/bin/activate
```

以下のエラーが出力されました。

```shell
$ source venv/bin/activate
bash: venv/bin/activate: No such file or directory
```

これは、activateファイルが作られていないというエラーです。

anacondaでインストールしたpythonを使っているとこういうエラーが出るそうです。

https://nsaito-nmiri.hateblo.jp/entry/2017/08/14/183045

## 対処法

virtualenvを使います。

ちなみに、virtualenvとvenvは違うもので、virtualenvはvenvの機能に加えて、python自身のバージョン管理も可能なようです。

https://mycodingjp.blogspot.com/2018/12/python-venv-virtualenv.html

https://scrapbox.io/miyamonz/venv%E3%81%A8virtualenv%E3%81%AE%E9%81%95%E3%81%84

それでは、実際にvirtualenvを使いたいのですが、virtualenvをインストールしていない方はインストールしましょう。

```shell
$ pip install virtualenv
```

準備は整ったので、仮想環境を構築しましょう！

プロジェクトディレクトリ内で以下のコマンドを実行してください。

```shell
$ pip install --upgrade virtualenv
$ virtualenv -p python3 venv
```

アクティベート！

```shell
$ source venv/bin/activate
```

## Tips

#### pythonのバージョン確認

```shell
(venv)$ python3 -V
```

#### パッケージのインストール

```shell
(venv)$ pip install package-name
```

#### 作成した環境にインストールしたパッケージ確認

```shell
(venv)$ pip freeze
```

#### インストールしたパッケージをrequirements.txtに書き込み

requirements.txtファイルは勝手に作成されます。もし既に存在していた場合は上書きされるので気を付けましょう。

```shell
(venv)$ pip freeze > requirements.txt
```

#### ディアクティベート

```shell
(venv)$ deactivate
```

## 参考

https://github.com/addok/addok/issues/553

https://virtualenv.pypa.io/en/latest/

https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e

https://www.sejuku.net/blog/68398
vscodeでeslintの補完が効かなくなった原因がeslintのv7からv8になったことだったので設定を修正したメモ

## 概要
`ncu -u && npm i`を行ってから、vscodeでファイル保存時にeslintの自動修正が動かなくなってしまった。
原因は、`dbaeumer.vscode-eslint`がデフォルトの設定だとv8に対応していない状態であることであった。
[version2.2.0](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)で、以下のように設定を行うように指示があったので、その通りに設定したら自動修正が復活した。


> Added support for ESLint V8.0 Beta. To stay backwards compatible with eslint settings the version still uses the CLIEngine if available. However users can force the use of the new ESLint API using the setting eslint.useESLintClass.`

## コード

```diff:.vscode/settings.json
{
  "files.eol": "\n",
  "editor.tabSize": 2,
  "editor.tabCompletion": "on",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "editor.formatOnSave": true,
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
  },
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],
  "eslint.format.enable": false,
+  "eslint.useESLintClass": true,
  "typescript.format.enable": false,
  "javascript.format.enable": false
}

```

<details><div>

```js:eslintrc.js
module.exports = {
  ignorePatterns: ['!.eslintrc.js', 'public'],
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier',
    'react-app',
    'react-app/jest',
  ],
  parser: '@typescript-eslint/parser',
  env: {
    browser: true,
    node: true,
    es6: true,
    jest: true,
  },
  parserOptions: {
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  settings: {
    react: {
      version: 'detect',
    },
  },
  rules: {
    'react/prop-types': 'off',
    'commma-dangle': 'off',
  },
}
```

```js:.prettierrc.js
module.exports = {
  semi: false,
  arrowParens: 'always',
  singleQuote: true,
  trailingComma: 'all',
}
```


```json:package.json
{
  "name": "aws-cartagraph-editor-client",
  "version": "0.0.0",
  "description": "CartaGraphEditor",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "test": "jest",
    "test-watch": "jest --watchAll",
    "serve": "vite preview",
    "eslint": "eslint .",
    "eslint-fix": "eslint . --fix"
  },
  "author": "hibohiboo",
  "license": "MIT",
  "dependencies": {
    "@reduxjs/toolkit": "^1.7.2",
    "firebase": "^9.6.7",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-redux": "^7.2.6",
    "react-router-dom": "^6.2.1",
    "web-vitals": "^2.1.4"
  },
  "devDependencies": {
    "@types/react-dom": "^17.0.11",
    "@typescript-eslint/eslint-plugin": "^5.12.0",
    "@vitejs/plugin-react-refresh": "^1.3.6",
    "eslint": "^8.9.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-config-react-app": "^7.0.0",
    "npm-check-updates": "^12.3.1",
    "prettier": "^2.5.1",
    "sass": "^1.49.8",
    "typescript": "^4.5.5",
    "vite": "^2.8.4"
  }
}
```

</div></details>
plotlyの図の背景の色を変更する

# 背景
plotly expressでグラフを書くと以下のような図になる。(ほんとはインタラクティブな図です…)
現状、図の背景の色がデフォルトで青となっている。
これを白に変えたい！

||図の背景|グリッド線の色|枠|
|-|:-:|:-:|:-:|
|デフォルト|青|白|なし|
|理想|**白**|**グレー**|**黒**|

```python
import pandas as pd
import plotly.express as px

# 使用するデータ
data = pd.DataFrame({"x" :[1,2,3,4],
                     "y":[1,2,4,8],
                     "label":["A","A","B","B"]})

fig = px.scatter(data,x="x",y="y",color="label",
                width=600,height=400)
fig
```
![newplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521553/317540e7-5adf-88d3-b506-132936dcc8f3.png)

# 結論
こんな感じになりました。

```python
fig = px.scatter(data,x="x",y="y",color="label",
                width=600,height=400)
fig.update_layout(plot_bgcolor="white")
fig.update_xaxes(linecolor='black', gridcolor='gray',mirror=True)
fig.update_yaxes(linecolor='black', gridcolor='gray',mirror=True)
```
![newplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521553/3e68ca61-3fbb-bdd2-d27a-c3c838121da8.png)

# 内容
まずは図の背景を白色にする。
`fig.update_layout(plot_bgcolor="white")`
ちなみにこの`white`の部分を変えると他の色に変更可能である。

次にグリッド線と枠の色を変更する。
x軸とy軸をそれぞれ設定する必要がある。
`fig.update_xaxes(linecolor='black', gridcolor='black',mirror=True)`
`fig.update_yaxes(linecolor='black', gridcolor='black',mirror=True)`

`gridcolor='black'` : グリッド線の色
`linecolor='black'` : 枠線の色 
`mirror` : デフォルトはFalse?　Trueにするとメモリの反対側にも枠線が反映される。
# 参考

https://plotly.com/python/axes/

https://plotly.com/python/reference/layout/
FontAwesomeでアイコンを挿入する


#はじめに

学習記録アプリを開発中で、学習履歴を一覧表示していました。そこに削除用のアイコンをつけたいと思い、今回FontAwesomeを導入していきます。

#環境
- rails 6.0.4.4
- ruby 2.6.5

#FontAwesomeの導入
FontAwesomeアカウントを登録したのちに、公式サイトのヘッダー部分の「Kits」をクリックします。
その後、自分専用コードをクリックすると埋め込み用のコードが表示されます。

``` application.html.erb
<script src="https://kit.fontawesome.com/自分専用コード.js" crossorigin="anonymous"></script>
```

これをHTMLファイルのhead要素内に記述します。
(今回はRailsなのでapplication.html.erbのhead要素内に記述する。)

補足
ちなみに登録はEmailとpasswordだけ入力すればすぐにできます。
FontAwesome公式 https://fontawesome.com/

# FontAwesomeの活用
欲しいアイコンを検索していきます。
今回は「ゴミ箱」のアイコンが欲しかったので「trash」で検索します。
(無料版なのでFREEにチェックを入れます。)
[![Image from Gyazo](https://i.gyazo.com/9cb94db8b1279ada5f16d06b5c5fe845.png)](https://gyazo.com/9cb94db8b1279ada5f16d06b5c5fe845)

気に入ったアイコンをクリックすると、コードが表示されるのでコピーします。
[![Image from Gyazo](https://i.gyazo.com/9562a5fc889e25afee7b03d5fdf599d0.png)](https://gyazo.com/9562a5fc889e25afee7b03d5fdf599d0)

あとはこれを自身のコードに貼り付ければアイコンが表示されて完了です。


# おわりに
今回は単純に導入だけでしたが、アイコンの色やサイズなど変更できるようです。
また、Kitsの導入方法以外にCDNを使ってFontAwesomeを読み込む方法があるそうです。Kitsの方には月1万PVまでの制限があるそうなので利用が多い際にはCDNでの導入が良いようです。

次はこのアイコンをクリックしたときのアクションを設定していきたいと思います。


# 参考
[Font Awesome のCSS版とJS版は何が違うの？](https://www.softel.co.jp/blogs/tech/archives/6103)
[【2021】今さら聞けないFont Awesomeの使い方やカスタマイズ方法](https://webdesign-trends.net/entry/14327)
Laravel ペジネーションリンクにクエリ文字列を追加する

#問題
クエリ文字列を使った検索結果等の一覧表示でペジネーションを使う際、2ページ目以降は未記入の表示になってしまう。

<details><summary>これが1ページ目なら、、、</summary>
<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522297/10d77c5a-048e-c851-9027-0c61eb5fd194.png"></details>

<details><summary>これが**2ページ目**</summary>
<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522297/1bb394c0-e11c-8c43-a10a-755b4a2ba459.png"></details>

原因は「クエリ文字列が次ページに繋げられていない」みたいです。

#解決法
###１．appendsメソッドの使用
appendsメソッドを使うことで、ぺジネーションリンクに指定のクエリ文字列を共通で渡すことができます。

```php:使用例
use App\Models\Board;

Route::get('/boards', function () {
    $board = Board::paginate(15);

    $boards->appends(['sort' => 'votes']);

    //
});
```

###２．withQueryStringメソッドの使用
withQueryStringメソッドを使うことで、ぺジネーションを利用しているリクエストのクエリ文字列をすべて渡すことができます。

```php:使用例
$boards = Board::paginate(15)->withQueryString();
```
自分の場合はこのメソッドで万事解決しました。

#参考サイト
[Laravel 8.X ぺジネーション クエリ文字列の追加](https://readouble.com/laravel/8.x/ja/pagination.html#appending-query-string-values)
選択範囲の小数点を切り上げるマクロ

1500行くらい修正しなきゃいけなかったため急いで書いたメモ。
自己責任でお願いします。

```
Sub RangeCelection()
Dim i As Range

'選択行をまわす
For Each i In Selection
    '切り上げ＆チェック関数呼び出し
    Call RoundUp(i)
Next
End Sub
```
```
Sub RoundUp(ByVal c As Range)
Dim target As Double
Dim target2 As Long

target = c.Value

'数値以外除外
If IsNumeric(target) Then
    Exit Sub
End If

'整数除外
If target = Int(target) Then
    Exit Sub
End If

'切り上げ
target2 = Application.WorksheetFunction.RoundUp(target, 0)

'イミディエイトに変更行と前の値を出しておいた
Debug.Print c.Row;
Debug.Print c.Value

c.Value = target2
End Sub
```
【CloudFront】オリジンパスとパスルールがごっちゃになったのでメモ

# CloudFrontのオリジンパスとパスルールがごっちゃになったのでメモ

オリジンパスもパスルールも値としてパスを指定するので、
初見だとどっちがどっちかごっちゃになっちゃったので備忘録として

- 前提:
  - `static`というバケット内に`photo1.jpg`というアクセスさせたい静的ファイルを配置
  - URLの末尾が /* (デフォルト)の場合 : LBのオリジンに割り振りたい
  - URLの末尾が /images/*の場合 : 静的ファイルを保存したS3バケットのオリジンに割り振りたい

# 正解
- パスルールを/images/*に設定して、オリジンパスは空白にする
- staticバケット内には`images`というフォルダを作成して、その中に`photo1.jpg`ファイルを配置する

# 以下勘違いによる失敗談

## オリジンパスがパスルールだと勘違いしていた

オリジンパスを設定したところでアクセス先オリジンを割り振りしてくれるわけではないのに、
パスルールと勘違いしてこっちだけ設定してたパターン

`images/*`のルールで`s3://static/photo1.jpg`にアクセスさせたいので、
オリジンパスを`/images`とする

パス自体は`https://example.com/images/photo1.jpg`にはなる
しかし、パスルールが設定されていないので、このリクエストはLBのオリジンに行っちゃうのでNG

移行前で、LB配下のウェブフロント側に同名のディレクトリがあると表示されちゃうから気づきにくいかもしれない

## バケット名がURLに入ると勘違いしていた

バケット名がURLに出てくることはないけど、
S3関連はバケット名から指定するものだという偏見があったパターン

`images/*`のルールで`photo1.jpg`にアクセスさせたいので、
`images`というバケットを作ろう！
  →S3バケットは一意じゃないといけないのでこんなありふれた名前では作成できないのでNG

## パスルールで指定したパスはS3のバケット内の構造と無関係と思っていた

このパターンが一番多いかもしれない

`images/*` で パスルールを設定しているから、 `https://example.com/images/photo1.jpg` のアクセスは
`s3://static/photo1.jpg`に行くはず！
  →/images/photo1.jpg と指定した場合、 `static`バケット内の`images/photo1.jpg`を見に行くので、そんなファイルはないと判断されてNG
  →つまり、`s3://static/images/photo1.jpg`とするのが正解


# おわりに

一回理解してしまえばなんでこんな単純なことを勘違いしていたんだろうかと思いますね、、
初めて使うサービスは落ち着いて`GettingStarted`をやってみるべきですね
Unity buttonのonclickに自作関数を設定できないときの対処法

#動機
buttonオブジェクトのonclickコンポーネントにいつものように自作関数を設定したい！
しかしその関数がリストされない！困った！
先達が見当たらないよわよわトラブルがあったので初心者なりにメモしておきます。
#対処法
**・関数のアクセス範囲をpublicにしていない**
**・スクリプトのアタッチされたオブジェクトを置かなければならない場所にスクリプトを直置きしている**
これらは先達がカバーしてくれているので以下のリンクからどうぞ。

[Unityの自作関数がボタンのOnClickに表示されない](https://teratail.com/questions/155388)

結論から言うと
**voidに設定していない**
ことが原因でした。そもそもよく考えたらどこに返り値を飛ばすんだよというお話で、焦らず外から必要なものをfindして呼び出しましょう！
onclickにreturn句は禁止でvoid一択です。
[ML] Loss Function

# Loss Function
ニューラルネットにおける学習では、パラメータを微小に変化させた時に起こる、損失関数の微小な変化を確認しながら、
損失関数を小さくする方向へとパラメータを更新していくことを繰り返す。
ニューラルネットワークの学習フェーズにて、的確な推論を行うために最適な各パラメータ(重みやバイアス)を決定する。
最適なパラーメータに近づけるための指標となるのが**Loss Function**になる
「推定値」と「実数値」の出力の誤差を表すものになる

## 平均二乗誤差 (MSE：Mean Squared Error)
Regression model
MSEは、最も一般的な損失関数として使われるだけでなく、主に回帰問題における出力層の評価関数としても用いられる。
いずれの関数から出力される値も、0に近いほどより良い。

```math
MSE = \frac{1}{m}\sum_{i=1}^{m}(\hat{Y}_i-Y_i)^2
```

## 交差エントロピー誤差 (Cross Entropy Error)
Classification model
pは真の確率分布、qは推定した確率分布
pとqの確率分布が似ていると交差エントロピー誤差は小さくなり、似ていないと交差エントロピー誤差は大きくなる。

```math
H(p,q)=−∑p(x)log(q(x))
```

## 勾配法 (Gradient Discent)
損失関数の最小値を探索するために、用いられる。
「勾配法」により、損失関数の最小化が完了すると、最適化されたネットワークのパラメータが設定され、学習が完了する。


# References
[損失関数とは？ニューラルネットワークの学習理論【機械学習】](https://rightcode.co.jp/blog/information-technology/loss-function-neural-network-learning-theory)
[交差エントロピー誤差をわかりやすく説明してみる](https://qiita.com/kenta1984/items/59a9ef1788e6934fd962)
40 代おっさん GASのFunctionオブジェクトについて学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## Functionオブジェクト

Functionオブジェクトは関数を取り扱うオブジェクト

構文

```javascript
new Function(仮引数1, 仮引数2, ..., 関数内の処理)
```

お試し

```javascript
function toshiki() {
  const sayHello = new Function('name', 'console.log(`こんにちは、${name}`)');
  sayHello('利樹');
}
```

Functionオブジェクトの主なメンバー

|分類|メンバー|戻り値|説明|
|----|--------|------|----|
|メソッド|toString|String|関数を文字列に変換して返す|
|プロパティ|length| |引数の数|
|プロパティ|name| |関数の名前|

お試し

```javascript
function toshiki() {
  const greet = (name, favorite) => {
    console.log("私は${name}君です。 ${favorite}が大好きです。");
  };

  console.log(greet.name);
  console.log(greet.length);
  console.log(greet.toString());
}
```

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
AWS Certified Data Analytics - Specialtyに合格したので勉強方法を書いておく

AWS Certified Data Analytics - Specialtyに合格したので、勉強方法を備忘として書いておきます。参考になれば幸いです。

職業：現在インフラエンジニア6年目でAWSをメインに設計構築をするようになって、2年くらい。
最近はもっぱらオンプレミスからAWSへの移行などのコンサルをやることが多いです。
AWSをやる前は、VMwareやWindows、Linuxなどいろいろやってましたが、
今では、AWSが得意！と言えるくらいになってます。

他のAWS関連の資格：
　ソリューションアーキテクトアソシエイト(SAA)(2018年取得)
　SysOpsアドミニストレータアソシエイト(SOA)(2019年取得)
　ソリューションアーキテクトプロフェッショナル(SAP)(2020年取得)
　セキュリティ – 専門知識（SCS）(2021年取得)
　デベロッパーアソシエイト（DVA）(2021年取得)
　クラウドプラクティショナー（CLF）(2021年取得)
　DevOpsプロフェッショナル (DOP）(2021年取得）
　データベース - 専門知識 (DBS) (2021年取得)
高度なネットワーク　― 専門知識 (ANS) (2021年取得)
※記載現在全資格を取得しているのですが、資格取得時の状態です。（サボっていてすみません・・・）
　
https://qiita.com/Regryp/items/0645fb976655262e9229

https://qiita.com/Regryp/items/2066ffca878e1726aa3c

https://qiita.com/Regryp/items/19f85ca4aec1940ca106

https://qiita.com/Regryp/items/228936a4c991ad925254

https://qiita.com/Regryp/items/fe5981bbd5585beb4864

https://qiita.com/Regryp/items/8f07932005197b47832c

勉強期間:１ヶ月くらい
私の場合、集中して長時間時間を取るということが苦手で、ほぼ毎日３０分〜４０分程度の時間をとってやっていました。

# 試験について
データ分析系は全然前提知識がなかったので、苦労しました。
データレイク、Hadoop、Apache Sparkや、EMR、Redｓｈｆｔ、Athena、QuickSight、Kinesis、IoT
などは特にBlackBeltを見るなどで前提の知識を身に着けました。


# 試験までに何をやるか
### 1.「AWS 認定試験に備える」を参照する
これは基本です。どの試験にも共通しますが、出題範囲、見るべきドキュメント、トレーニングが列挙されています。
基本的に私の勉強方法は以下URLのリンク先を潰していくことがメインとなります。
学習のヒントとして、出題範囲や、参考とするドキュメントなど事細かにリンクが載っていますので、
最初に見ることをおすすめします。

https://aws.amazon.com/jp/certification/certification-prep/

### 2.試験ガイド、サンプル問題を読む
出題される分野、配分、問題の形式をしっかり読みましょう。
配分は以下のとおりです。

第1分野: 収集 18%
第2分野: ストレージとデータ管理 22%
第3分野: 処理 24%
第4分野: 分析と可視化 18%
第5分野: セキュリティ 18%

[試験ガイド](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-data-analytics-specialty/AWS-Certified-Data-Analytics-Specialty_Exam-Guide.pdf)
[サンプル問題](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-data-analytics-specialty/AWS-Certified-Data-Analytics-Specialty_Sample-Questions.pdf)

### 3.本を読む
以下の本を購入しました。
試験対策というより、AWS上でのデータレイクに関する説明やデモが載っている本です。
https://www.amazon.co.jp/dp/491031301X/ref=cm_sw_em_r_mt_dp_1V71AVN1SBECRADRH0GB

### 4.試験対策のコースを実施する
以下のUdemyのコースを一通りやりました。
全編英語ですが、Edgeの翻訳機能を使うと字幕を日本語化できるのでおすすめです。
体系的に学ぶのにはちょうどよいコースだと思いました。

https://www.udemy.com/course/aws-data-analytics/

公式のトレーニングもあるので、こちらもおすすめです。
https://explore.skillbuilder.aws/learn/course/external/view/elearning/51/exam-readiness-aws-certified-data-analytics-specialty?das=sec&sec=prep


### 5.問題集を解く
aws WEB問題集で学習しようのサイトにて、ANSの問題を2周しました。
やはり、問題集を解くことが一番ためになります。試験で求められる知識をチェックできる、間違えた問題から苦手な分野、深堀りすべきドキュメントが参照できるというところがあるので、一番おすすめです。

https://aws.koiwaclub.com/

Udemyの問題集も購入して解いて見ました。
※セールのときに購入するのがおすすめです。

https://www.udemy.com/course/aws-certified-data-analytics-specialty-practice-exams-amazon/

公式の模擬試験も最近無料になったみたいです。
https://explore.skillbuilder.aws/learn/catalog?ctldoc-catalog-0=se-%22AWS%20Certification%20Official%20Practice%20Question%20Sets%22?das=sec&sec=prep

### 6.ホワイトペーパー、よくある質問、BlackBeltを見る
全体的に苦手な分野を軽く目を通すレベルでよいかなと思います。
私の場合、DirectConnectのBlackBelt、よくある質問を軽く眺めました。

https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/#management-admin

# 最後に
データ解析を主でやってる方は簡単かもしれませんが、あまりとっつきのない私にとっては非常に難しかったです。
本番でもよくわからない問題も多数、、、なんとか合格できましたね
Reactのチュートリアルをやってみた①

#はじめに#
- Reactを使って画面作成をしてみたいと思うようになり、サイトを調べて`https://ja.reactjs.org/tutorial/tutorial.html`を試しにやってみました。
- ここにかかれていることをサイト内にあるスターターコード`https://codepen.io/gaearon/pen/oWWQNa?editors=0010`を使って試したものになります。
    - ○×ゲームを作ることが題材となっています。
- スターターコードにチュートリアルに従いコードを書いていくことで動きを確認することはできました。
- 今回は、チュートリアルを進めていく中で、`props`と`state`について自分が理解したイメージを纏めておきたいと思います。
    - 技術的ではないかもしれません

#実行したことと理解したイメージ#
Reactを理解するために、Webの画面上に表現される複雑なユーザーインターフェースをコンポーネントと呼ばれる小さく独立した部品で構成されることの説明から始まる。
３×３の○×ゲームを作るにあたって、
- Squareという名前のコンポーネント：1マスの動きを表現するための部品
- Boardという名前のコンポーネント：部品のSquareを３×３で表現するための部品
- Gameという名前のコンポーネント： ボード上に表現されたSquareの情報をもとに勝敗やゲームの流れをコントールするための部品
を用意して、処理を行っていくことになる。
Reactにいくつか異なる種類のコンポーネントがあるが、ここでは`React.Componet`について学ぶことができる

コードは、Reactのチュートリアルのサイトを見て頂きたいが、ここでは、コードを書きながら進んでいくので、その内容をイメージでとらえてみる。

まず初めに、Reactコンポーネントを3つ用意します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/07edc0fe-d21e-c0c1-aa79-738d51bd4a32.png)


Reactコンポーネントでは、`props`、`state`を使って情報を描画していきます。
ひとまず、私の理解は、こんな感じです。
　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/bc0878ae-671a-26ee-6409-ec17b962246b.png)


### Propsは、引数のデータが格納されるエリアとは ###
チュートリアルでは、9つのマス目に、０～８の数字を描画していきます。
やりたいことは、こんな感じ
　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/a44d06b2-3db2-782d-2f3a-3db977fb61b6.png)

`Board`から`Props`を使って、`Square`に渡して数字の描画を行いました。
プログラムとしては、チュートリアルに従い、
`Board`は、このように書きました。

``` react
class Board extends React.Component {
  renderSquare(i) {
    return <Square value={i} />;
  }
}
```

`square`は、このように書きました。

``` react
class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {this.props.value}
      </button>
    );
  }
}
```

上記のようにコードを書いた場合の描画までの流れをイメージにしてみました。
　　　　　<img width="75%" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/fbe35dd2-bb8b-9a07-dc13-1ae3aff7fa35.png">

### state は、データを記憶しておくエリアとは ###
チュートリアルでは、マス目をClickされたら、X が描画できるようにしていきます。
やりたいことは、こんな感じ
　　　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/17b2f5c0-e584-ad05-b9d3-5fa50fbcd140.png)

`Square`がクリックされたことを検知して、’X'を記憶して、ボタン名に’X’と描画できるようにする
`Square`だけ、チュートリアルに従い、以下のように書き換えました。

``` react
class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }

  render() {
    return (
      <button className="square" onClick={() => this.setState({value: 'X'})}>
        {this.state.value}
      </button>
    );
  }
}
```

上記のようにコードを書いた場合の描画までの流れをイメージにしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518581/6f269731-089b-fc3c-2294-2cd9b349f4e0.png)


#まとめ#
- `Props`は、親から名付けられた変数名で値が格納され、子は、その名前の変数名で値を受け取ることができる
- `State`は、自身のcomponent内で状態を記録しておくことができる
- したがって、親から引数として渡される`this.props.value`と`this.state.value`は、同じ`value`であるが、異なるものであることを理解しておくことが<font color="Red">**ポイント**</font>だと理解しました。
Visual Studio Codeの設定をクリーンアップする

Visual Studio Codeの設定やエクステンションをクリーンアップしたい。
一つ一つ設定をいじるのではなく、

- 全ての設定をいったん削除して
- 必要なものだけ入れ直す

をやりたい。

## 確認環境
- MacBook Pro (16-inch 2019)
- macOS Monterey 12.0.1

## 手順

設定とエクステンションはそれぞれ以下の場所にあるので、バックアップをとってから全部削除し、必要なものを入れ直せば良い。

```sh
# 設定
$HOME/Library/Application Support/Code/User/settings.json

# エクステンション
~/.vscode/extensions
```

以上

## 参考
- How to reset settings in Visual Studio Code?
    - https://stackoverflow.com/questions/36108515/how-to-reset-settings-in-visual-studio-code
プリンシパルがややこしい

## 勉強前イメージ

AWSアカウントってこと？IAMのやつ難しい・・・

## 調査

### IAMのプリンシパル とは

#### プリンシパル

アクションを実行する人、ユーザ、アプリケーションを指す

#### プリンシパル要素

リソースへのアクセスを許可または拒否するプリンシパル(↑でいうとアクションを実行する人、ユーザ等)を指定します。
リソースベースポリシーに記述します。
Webコンソールのロールから 信頼関係にて設定できます。

![1IAM Management Console - Google Chrome 2022-02-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/24d13ccf-c54d-a816-cd21-bdbebfa99f56.png)

ポリシーでは以下を指定できます。

- AWSアカウント・ルートユーザ
- IAMロール
- ロールセッション
- IAMユーザ
- フェデレーティッドユーザーセッション
- AWS のサービス
- すべてのプリンシパル


書き方としては以下になります。
大文字小文字は区別されて *(ワイルドカード) は使えません。

- "Principal": { "AWS": "arn:aws:iam::123456789012:root" }
- "Principal": { "AWS": "arn:aws:iam::123456789012:user/user/alice" }
- "Principal": { "AWS": "arn:aws:iam::123456789012:user/role/ロール" }

## 勉強後イメージ

要するに、「アクセスしていいよ！ or だめだよ！」のユーザとかアプリケーションがプリンシパルで、
プリンシパル要素は、リソースベースのポリシーのJSONを書くときに「アクセスしていいよ！ or だめだよ！」のユーザとかを書くところ？
IAM難しい・・・・

## 参考

- [IAM の仕組みについて](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/intro-structure.html)
- [【AWS Black Belt Online Seminar】AWS Identity and Access Management (AWS IAM) Part1](https://www.youtube.com/watch?v=K7F5yTThynw)
PerlとPythonでありがちな配列検索処理の書き方

久々に忘れたのでメモ

## 完全一致

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330873/e6e9d7cc-e827-4efe-c840-3b1602780cea.png)

### Perl

```pl:grep1.pl
use strict;
use warnings;
my $text = "AAA";
my @lst1 = ( "AAA",  "BBB", "CCC" );
# 完全一致
if ( grep $text eq $_, @lst1 ) {
        print("match1\n"); # match1が出力
}
```

### Python

```py:grep1.py
text = "AAA"
lst1 = ["AAA", "BBB", "CCC"]
# 完全一致
if text in lst1:
    print("match1") # match1が出力
```

## 部分一致

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330873/19a3e267-3d2c-c46c-20a8-af75af72ba9d.png)

### Perl

```pl:grep2.pl
use strict;
use warnings;
my $text = "AAA";
my @lst2 = ( "AAAA", "BBB", "CCC" );
# 部分一致
if ( grep /$text/, @lst2 ) {
        print("match2\n"); # match2が出力
}
```

### Python

```py:grep2.py
text = "AAA"
lst2 = ["AAAA", "BBB", "CCC"]
# 部分一致
if [True for _ in lst2 if text in _]:
    print("match2") # match2が出力
```

## 逆部分一致

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330873/87b13db1-d4fb-a6fd-9773-b1595d983187.png)

### Perl

```pl:grep3.pl
use strict;
use warnings;

my $text = "AAA";
my @lst3 = ( "A",    "B",   "C", "D" );
# 逆部分一致
if ( grep $text =~ /$_/, @lst3 ) {
        print("match3\n"); # match3が出力
}
```

### Python

```py:grep3.py
text = "AAA"
lst3 = ["A", "B", "C"]
# 逆部分一致
if [True for _ in lst3 if _ in text]:
    print("match3") # match3が出力
```
Docker環境でphp artisan tinkerが通らない

php artisan tinkerが通らない！他のartisanコマンドは通るのに。。。

## エラー
```bash
Writing to /var/www/.config/psysh is not allowed.
```

原因はホームディレクトリ「/var/www」の権限不足。
root権限でしか触ることができないが、別のユーザーを使っていたので権限エラーがでていた。

# やったこと>権限を変更

```bash
$ sudo chmod -R 777 /var/www/
```

sudoコマンドが入っておらずエラー。。
find . -name sudo
見つからず。

# 解決法
ホームディレクトリの所有者を変更する。
docker-fileに以下追加。再ビルドで通った
ちなみに-Rオプションは再帰的に権限を所有者を書き換える 

```docker
ARG HOME_DIR='/var/www'
RUN mkdir -p $HOME_DIR
RUN chown -R $UID:$GID $HOME_DIR
```

# 参考
[dockerでHOMEディレクトリを設定する](https://qiita.com/reflet/items/0ec4f67ee29ac5e0de24)
[sudoコマンド入れるなら](https://zenn.dev/sa2knight/articles/1edb06187307e7)
[Rails] FactoryBotの実装

# FactoryBot
FactoryBotはRailsでテストサンプルデータを簡単に扱えるように考えられたgem。
rspecと組み合わせて使われる例をよく見ます。

##使い方
###初期設定
```ruby:spec/rails_helper.rb
config.include FactoryBot:Syntax::Methods # Rspec.configureの中に記述
```

###Factoryの定義
```ruby:spec/factories/ex.rb
FactoryBot.define do
  factory :ex_user do
    name {"user1"}
    password {"password"}
  end
end
```
上記の例ではfactoryの名前がex_userでその中に名前とパスワードが格納されています。

###Specへ記述
```ruby:specテスト内
example "xxxのテスト"
 m = build(:ex_user)
end
```
ex_userをspec内でbuildすることで、テスト内で使用可能になる。

###小技
```ruby:specテスト内
example "xxxのテスト"
 m = build(:ex_user, password:"hogehoge")
end
```
build時にobject内の値を変更することもできる。
上記はパスワードをhogehogeに変更してbuildしている。

#まとめ
FactoryBotは使い勝手が良く、奥が深い。
Javaで重複した順位付けをする方法

# Javaで順位付けする方法
どうやって順位付けを行うのか、考えたことはありますか？
結構コードを書いていて、最初はぐちゃぐちゃしたものになってしまっていたので、自分で試してみた方法を上げてみたいと思います。

# 環境
- java14

# 使用させていただいたデータ
[ワインの評価データ](https://domohelp.domo.com/hc/ja/articles/360043931814-%E6%A5%BD%E3%81%97%E3%81%BF%E3%81%AA%E3%81%8C%E3%82%89%E5%AD%A6%E3%81%B6%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88)

今回はワインの評価データのポイントが高い上位30番以内のデータを出力します。
同率順位も可能性としてはあるので、この場合は30個を超えることもあります。
例えば、ポイントが2,2,3,3,5,5,8,8,8,9,12であり、この上位３位まで出力する場合、
```
1位 12
2位 9
3位 8
3位 8
3位 8
```
となります。

# 実際書いたコード
for文で行ったりする方法も考えられると思います。
また、sort部分はクイックソートなどを使っても効率化される場合もあると思います。

今回私が意識したのは、「可読性」です。できるだけシンプルかつ、読みやすいコードです。
どうしても`stream`を使って行いたかったので、今回は`Map`を使用することにしました。
色々やり方はあるとは思いますが、今回はKeyをポイント、そしてEntityをワインのモデルの`List`とすることにします。

それが以下のコードです。

```Java
    public static Map<Integer, List<WinModel>> getSortedWinModelMapByWinModelList(List<WinModel> winModelList) {
        return winModelList.stream()
                .collect(Collectors.groupingBy(WinModel::getPoints))
                .entrySet().stream()
                .sorted(Collections.reverseOrder(Map.Entry.comparingByKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    }
```

コードの解説です。

csvファイルで読み取ったデータは全てワインのモデルに変換し、`List`に格納しています。
その`List`が、上記のメソッドの引数である`winModelList`です。
Keyをポイント、そしてEntityをワインのモデルの`List`とするときには、`.collect(Collectors.groupingBy())`を使います。`groupingBy()`の中に、まとめたいもののキーを記述します。今回はポイントでグルーピングしたいので、下記のようなコードになりました。

```Java
.collect(Collectors.groupingBy(WinModel::getPoints))
```

さらに、今回はポイント(キー)で降順にソートしたいため、以下のように記述します。

```Java
.sorted(Collections.reverseOrder(Map.Entry.comparingByKey()))
```
なお、ソートのときには昇順のときには`naturalOrder()`を使います。

ソートしたあと、きちんと`Map`に戻す必要があるので、

```Java
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
```

あとはこの関数に、先程のMapと何番目まで出力するのか決めた数字を引数で渡し、出力してあげます。

```Java
    public static void printResult(Map<Integer, List<WinModel>> winMap, int num) {
        int rank = 1;

        for (Integer key : winMap.keySet()) {
            if (rank > num) {
                break;
            }

            for (WinModel winModel : winMap.get(key)){
                System.out.println(rank + " " + winModel.getPoints() + " " + winModel.getDesignation());
            }

            rank += winMap.get(key).size();
        }
    }
```

３０番目までの出力は、

```
1 100 En Chamberlin Vineyard
1 100 Rare
・・・（中略）・・・
23 99 Madonna delle Grazie
23 99 Cailloux Vineyard
23 99 Royal City Stoneridge Vineyard
・・・（中略）・・・
```

となりました。うまく行きました。

# 最後に
ソートだけでも結構考えさせられることがあるなと改めて感じました。
プログラミングは興味深いですね。