OmniAICreator/Qiita-1.07M huggingface dataset:
LeetCodeの練習メモ

LeetCodeのEasy問題を解いていくテスト

11/27
1.two sum
問題文
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/1f3dbee3-ca7a-975d-a4d8-defb92983b4f.png)
日本語
整数の配列 nums と整数の target が与えられた場合、合計が target になる二つの数のインデックスを返します。

各入力には必ず一つの解があると仮定しても構いませんが、同じ要素を二度使用することはできません。

答えは任意の順序で返すことができます。

回答例

```python
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashmap = {}

        for i in range(len(nums)):
            num = nums[i]
            complement = target - num
            if num in hashmap:
                return [hashmap[num],i]
            else:
                hashmap[complement] = i
```        

9. Palindrome Number
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/b0b8044c-2326-2a1c-ac11-9a66d1cf483f.png)
逆数の一致

```python
class Solution:
    def isPalindrome(self, x: int) -> bool:
        
        if str(x) == str(x)[::-1]:
            return True
        else:
            return False
```    

11/28
13. Roman to Integer
問題
ローマ数字は7種類の記号で表される： I、V、X、L、C、D、M。

記号 値
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例えば、2はローマ数字でIIと書き、2つの1を足しただけである。12はXIIと書き、これは単にX＋IIである。27はXXVIIと書き、これはXX＋V＋IIである。

ローマ数字は通常、左から右に大きいものから小さいものへと書く。しかし、4を表す数字はIIIIではない。代わりに4はIVと書く。1が5の前にあるので、それを引くと4となる。同じ原理が数字の9にも当てはまり、IXと書く。引き算が使われる例は6つある：

IをV（5）とX（10）の前に置くと4と9になる。
XをL（50）とC（100）の前に置くと、40と90になる。
CをD（500）とM（1000）の前に置くと、400と900になる。
ローマ数字が与えられたら、それを整数に変換しなさい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/ec288695-7c2d-6dc4-f020-9742a60a821e.png)

```python
class Solution:
    def romanToInt(self, s: str) -> int:
        roman={'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
        number=0
        for i in range(len(s)-1):
            if roman[s[i]] < roman[s[(i+1)]]:
                number-=roman[s[i]]
            else:
                number+=roman[s[i]]
        return number+roman[s[-1]]
```    
20. Valid Parentheses
問題
文字 '(', ')', '{', '}', '[', ']' を含む文字列 s が与えられたとき、その入力文字列が有効かどうかを判定する。

入力文字列が有効であるのは、以下の場合である：

開き括弧は、同じ種類の括弧で閉じなければならない。
開き括弧は正しい順序で閉じなければならない。
どの閉じ括弧にも、対応する同じ型の開き括弧がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190712/73f236e0-c4ae-d0e6-b62c-817fb4924fc3.png)
```python
class Solution:
    def isValid(self, s: str) -> bool:
        opcl = dict(('()','[]','{}'))
        stack = []

        for idx in s:
            if idx in '([{':
                stack.append(idx)
            elif len(stack) == 0 or idx != opcl[stack.pop()]:
                return False
        return len(stack) == 0
```
AWSのクレジット適応ができるサービスの確認の仕方

## はじめに
ありがたいことに、AWSのクレジットを頂ける機会があるかと思います。
ですが、対象サービスが何かわからない方もいらっしゃるかと思うので、対象サービスの確認方法を記載します。

## AWSの公式ドキュメント(法務関連）からの確認
私が冒頭に記載したクレジットとは、販促クレジット(AWS Promotional Credit)を指します。
[こちら](https://d1.awsstatic.com/legal/termsandconditions/AWS_Promotional_Credit_Terms_and_Conditions_2021-06-01_Japanese.pdf)に詳細が書かれております。

>販促クレジットは、お客様が該当する販促クレジットコードをご自身の AWS アカウントに適用した請求期間中、またはそれ以降に発生した料金および代金であってお客様の AWS 契約事業体により指定された特定のサービス（総称して「対象サービス」）についてのみ使用することができます。販促クレジットは、Amazon Mechanical Turk、AWS マネージドサービス、対象外の AWS サポート、AWS マーケットプレイス、AWS プロフェッショナルサービス、AWS トレーニング、AWS 証明書、 Amazon Route 53ドメインネームの登録もしくは移転、仮想通貨のマイニング向けサービス、または AWS 契約事業体が指定するその他本サービスの料金および代金、あるいはセービングプランやリザーブドインスタンスなどの本サービスの前払金（総称して「対象外サービス」）に使用することはできません。本第 1 条において、「対象外の AWS サポート」とは、企業サポートレベルに該当する AWS サポート（AWS サイトに規
定）をいいます。

なお、冒頭に以下のような記載があります。
>以下の翻訳は情報目的のみで提供されます。本翻訳版と英語版の間に差異、不一致、矛盾が存在する場合、（特に翻訳による遅れもあり）英語版が優先します。

なお、英語版は[こちら](https://aws.amazon.com/awscredits/?nc1=h_ls)です。今回日本語版で転載した箇所と同箇所を引用します。
特に引用箇所に絞れば、差異はなさそうですね。

>1. Promotional Credit will be applied only to offset eligible fees and charges incurred during or following the billing cycle in which you apply the applicable Promotional Credit code to your AWS account.  Promotional Credit will be applied only to the specific Services designated by your AWS contracting entity (collectively, “Eligible Services”). Promotional Credit will not be applied to any fees or charges for Amazon Mechanical Turk, AWS Managed Services, Ineligible AWS Support, AWS Marketplace, AWS Professional Services, AWS Training, AWS Certification, Amazon Route 53 domain name registration or transfer, any Services for mining for cryptocurrency, any other Services as may be designated by your AWS contracting entity, or any upfront fee for any Services such as Savings Plans and Reserved Instances (collectively, “Ineligible Services”). For purposes of this Section 1, “Ineligible AWS Support” means AWS Support (as described on the AWS Site) that is at the Enterprise Support level.

## AWSマネージドコンソールからの確認方法
次にAWSマネジメントコンソールからの確認方法となります。
Billing Management Consoleより、クレジットを選択すると以下の画面が表示されます。赤枠で囲んでいる、「サービスの完全なリストを表示」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490859/02a4d543-fbcb-a15b-5dd1-290e8c0299e1.png)


するとこのようにAWSマネージドコンソールから対象サービスを確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490859/b456b5bd-5d2d-6fbe-83cc-54c38b5e1648.png)

## まとめ
いかがでしたか？
私個人は、Route 53のドメイン登録とかもクレジットで相殺できると思い込んでおりました。（反省）
クレジット枠でAWS環境を利用されたい方は、是非AWS公式ドキュメントやAWSマネージドコンソールから事前確認されることをお勧めします。
なお、英語版のAWS 販促クレジット条件が優先されますので、英語版をご確認ください。

また、うまく相殺されない等トラブルがある方は、まずは[こちら](https://repost.aws/ja/knowledge-center/aws-promotional-credit)も確認することをお勧めします。
静的サイトリソースのキャッシュの動作

https://help.salesforce.com/s/articleView?id=sf.sites_caching.htm&type=5
抜粋：
画像、スタイルシート、スクリプトなどの静的サイトリソースは、リソースの [キャッシュコントロール] 属性に基づいてキャッシュされます。詳細は、Salesforce ヘルプの「静的リソースの定義」を参照してください。

https://help.salesforce.com/s/articleView?id=sf.pages_static_resources_create.htm&type=5

抜粋：
また、以前は無制限であったサイトに制限が設定されると、Salesforce キャッシュおよび中間キャッシュから静的リソースが解放されるまでに最大 45 日かかる場合があります。

いろいろ難しいことを書いてあります。
通常、本番公開前にゲストユーザーを繰り返して公開、非公開する場合はよくあります。この場合は、静的リソースを更新するたびに、リリース名を同時変更した方が無難だと思われます。

Salesforceのくせを極めることも一つの選択肢でありますが、簡易な解決案（Better Practice）があれば、極めるに費やす時間をもっと業務なところに使うべきでしょう
日本語プログラミング言語 スミレ Java C# で関数を介した整数カウントアップ実行時間を仲良く競う

# はじめに
日本語プログラミング言語 プロデル とJava C# とで関数呼び出しを介した整数カウントアップの反復実行時間を仲良く競い合わせてみます。いわゆるファンクションコールのオーバーヘッドとはどんなものなのかを切り分けます。スミレはプロデルコンパイラ2.0で検証したソースコードをスミレコンパイラ1.9でコンパイルし、C#と同じ.NET Core 6で実行してみます。


## この記事内容の作業環境
Windows11 Pro 22H2
VSCode(Visual Studo Code)　1.78.2
java Eclipse Adoptium jdk-20.0.2.9-hotspot
C# 10 dotnet-sdk-6.0.404-win-x64
sumire Version 1.9.1191
CPU Intel(R) Core(TM) i3-5005U 2.00 GHz


## この記事内容の保証
※この記事の実行結果は参考情報です。実行環境に大きく依存します。

## 参考記事
### プロデルの結果
[日本語プログラミング言語 プロデル Java C# で関数を介した整数カウントアップ実行時間を仲良く競う](https://qiita.com/mylifewithviolin/items/d7f8b5b94ce1d40ee904)

### スミレ とは
[日本語プログラミング言語 スミレ とは](https://qiita.com/mylifewithviolin/items/8f90f8452d65439fd825)
# お題のソースコード
#### Java
お手数ですが[参考記事 プロデルの結果](https://qiita.com/mylifewithviolin/items/d7f8b5b94ce1d40ee904)をご参照ください。

#### C#
お手数ですが[参考記事 プロデルの結果](https://qiita.com/mylifewithviolin/items/d7f8b5b94ce1d40ee904)をご参照ください。

#### スミレ
```mind:callfunc.rdr
※コンソール
    【count:整数】は、0
    【countMax:整数】は、0
    
    もしプログラムのコマンドライン引数が無なら
    　　countMax=0
    そうでなければ
       例外監視
    　　  countMax=プログラムのコマンドライン引数(1)
    　　発生した場合
     　　 countMax=0
        監視終わり
    もし終わり
    
    開始日時は、今日
    count < countMaxの間、繰り返す
    
       	countをカウントアップしたものをcountに代入する
    	//count =　countをカウントアップする
    繰り返し終わり
    終了日時は、今日
    時間差は、終了日時-開始日時
    
    「処理回数：」＆ count＆ 「回」をコンソールへ表示して改行する
    「処理時間：」＆ 時間差の合計ミリ秒数＆ 「ミリ秒」をコンソールへ表示して改行する

【c:整数】をカウントアップする手順
     c = c +1
     cを返す
終わり

```
プロデルと同一のソースコードです。
日本語構文
```
countをカウントアップしたものをcountに代入する
```
の方です。

# 実行結果
#### Java
お手数ですが[参考記事 プロデルの結果](https://qiita.com/mylifewithviolin/items/d7f8b5b94ce1d40ee904)をご参照ください。

#### C#
お手数ですが[参考記事 プロデルの結果](https://qiita.com/mylifewithviolin/items/d7f8b5b94ce1d40ee904)をご参照ください。

#### スミレ

```:
C:\sumire\evalution>\sumire\sumire.exe callfunc.rdr 40
処理回数：40回
処理時間：57.761ミリ秒

C:\sumire\evalution>\sumire\sumire.exe callfunc.rdr 400
処理回数：400回
処理時間：63.6014ミリ秒

C:\sumire\evalution>\sumire\sumire.exe callfunc.rdr 4000
処理回数：4000回
処理時間：109.7499ミリ秒

C:\sumire\evalution>\sumire\sumire.exe callfunc.rdr 40000
処理回数：40000回
処理時間：493.4095ミリ秒

C:\sumire\evalution>\sumire\sumire.exe callfunc.rdr 400000
処理回数：400000回
処理時間：3021.9449ミリ秒

C:\sumire\evalution>\sumire\sumire.exe callfunc.rdr 4000000
処理回数：4000000回
処理時間：29375.8565ミリ秒

C:\sumire\evalution>\sumire\sumire.exe callfunc.rdr 40000000
処理回数：40000000回
処理時間：283792.7766ミリ秒

C:\sumire\evalution>\sumire\sumire.exe callfunc.rdr 400000000
処理回数：400000000回
処理時間：2681275.2056ミリ秒

C:\sumire\evalution>
```
スミレの公式サイトにある実行方法に準じて実行してみましたが、この方法ですと最初にソースコードを中間コードに事前コンパイルするオーバーヘッドが乗っかってしまいますので、中間コードファイルの生成オプションがないか確認してみましたが、なさそうでしたので、この結果を比較対象とします。

# 実行結果まとめ
表3　関数経由の整数カウントアップの反復実行時間（ミリ秒）
| 実行回数 | Java | C# | スミレ |
|-:|-:|-:|-:|
|  40 |  0 | 6  |  57 |
| 400  | 0  | 6  | 63 |
| 4,000  | 0  | 6  | 109  |
| 40,000  | 0  | 6  | 493  |
| 400,000  | 2  | 11 | 3,021  |
| 4,000,000  | 3  | 62  | 29,375  |
| 40,000,000  | 5  | 538  | 283,792  |
| 400,000,000  | 6  | 5,304  | 2,681,275  |

※ナノ秒台は切り捨て

# おわりに
いかがでしたでしょうか？整数カウントアップの関数呼び出しを単純にループさせているだけですので、各言語、実装によってはいろいろな差異がでるものと思われますので、この件はあくまで参考情報です。
plunkerでd3 その13

# 概要
plunkerでd3やってみた。
練習問題、やってみた。

# 練習問題
オブジェクトからd3.hierarchy用の木構造を写し取る。

# 方針
- 再帰でやる。

# サンプルコード

```
function maketree(obj) {
	var obj2 = {};
	Object.keys(obj).forEach(function(key) {
		if (key == "Name")
		{
			obj2["name"] = obj.Name.Data;
		}
		if (key == "Children")
		{
			if (obj.Children != [])
			{
				obj2["children"] = [];
				obj.Children.forEach((childNode) => {
					obj2.children.push(maketree(childNode));
				});
			}
		}
	})
	return obj2;
}
```

# 実行結果

```
{"name":"test1","children":[{"name":"T","children":[{"name":"Visual","children":[{"name":"Canvas","children":[{"name":"Image","children":[{"name":"Image","children":[{"name":"ConnectPoint","children":[]}]},{"name":"Vertical Layout","children":[{"name":"Text","children":[]}]}]}]}]}]},{"name":"Display","children":[{"name":"Visual","children":[{"name":"Canvas","children":[{"name":"Image","children":[{"name":"Image","children":[{"name":"ConnectPoint","children":[{"name":"Wire","children":[]}]}]},{"name":"Vertical Layout","children":[{"name":"Vertical Layout","children":[{"name":"Text","children":[]}]}]}]}]}]}]}]}
```

# 成果物

https://embed.plnkr.co/plunk/Q0aBjYEwYh836YI6


以上。
JavaScriptのfalsy,trusyな値チェック

# falsy

```javascript
// Falsyな値のリスト
const falsyValues = [false, 0, -0, "", '', ``, null, undefined, NaN];

// 各falsy値をチェックし、コンソールに出力する
falsyValues.forEach(value => {
  console.log(`値: ${value}, 型: ${typeof value}, Falsyかどうか: ${!value}`);
});
```



# trusy

```javascript
// Truthyな値の例
const truthyValues = [true, 1, -1, "文字列", '別の文字列', `テンプレートリテラル`, [], {}, function() {}, Infinity, -Infinity];

// 各truthy値をチェックし、コンソールに出力する
truthyValues.forEach(value => {
  console.log(`値: ${value}, 型: ${typeof value}, Truthyかどうか: ${!!value}`);
});

```
plunkerでd3 その12

# 概要
plunkerでd3やってみた。
練習問題、やってみた。

# 練習問題
v5でtree表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0c158154-94f9-8a06-4d47-10c1be557178.png)

# サンプルコード

```
	var width = document.querySelector("svg").clientWidth;
	var height = document.querySelector("svg").clientHeight;
	var data2 = {"name":"test1","children":[{"name":"T","children":[{"name":"Visual","children":[{"name":"Canvas","children":[{"name":"Image","children":[{"name":"Image","children":[{"name":"ConnectPoint","children":[]}]},{"name":"Vertical Layout","children":[{"name":"Text","children":[]}]}]}]}]}]},{"name":"Display","children":[{"name":"Visual","children":[{"name":"Canvas","children":[{"name":"Image","children":[{"name":"Image","children":[{"name":"ConnectPoint","children":[{"name":"Wire","children":[]}]}]},{"name":"Vertical Layout","children":[{"name":"Vertical Layout","children":[{"name":"Text","children":[]}]}]}]}]}]}]}]};
	root = d3.hierarchy(data2);
	var tree = d3.tree().size([height, width - 160])
	tree(root);
	g = d3.select("svg").append("g").attr("transform", "translate(80,0)");
	var link = g.selectAll(".link").data(root.descendants().slice(1))
		.enter().append("path").attr("class", "link")
		.attr("d", function(d) {
			return "M" + d.y + "," + d.x +
				"C" + (d.parent.y + 100) + "," + d.x +
				" " + (d.parent.y + 100) + "," + d.parent.x +
				" " + d.parent.y + "," + d.parent.x;
		});
	var node = g.selectAll(".node").data(root.descendants())
		.enter().append("g").attr("class", "node")
		.attr("transform", function(d) { 
			return "translate(" + d.y + "," + d.x + ")"; 
		});
	node.append("circle").attr("r", 8).attr("fill", "#999");
  node.append("text").attr("dy", 3).attr("x", function(d) { 
		return d.children ? -12 : 12; 
	}).style("text-anchor", function(d) { 
		return d.children ? "end" : "start"; 
	}).attr("font-size", "200%").text(function(d) { 
		return d.data.name; 
	});




```

# 成果物

https://embed.plnkr.co/plunk/KnTSr1taXiAGkROx


以上
本当に理解している？selfとSelfの違い！

# selfとSelfとは？
### selfとは？
型の内部のプロパティやメソッドなどの中ではselfキーワードを通じてインスタンス自身にアクセスできます！
例
```Swift:self.playground
class Person {
    let personName = "ひなっこ"
    func sayName() {
        print(self.personName)
    }
}
```
### Selfとは？
型の内部のプロパティやメソッドなどの中ではSelfキーワードを通じて型自身にアクセスできます！
Selfキーワードを使うと、型自身に紐づくメンバーであるstaticメソッド、staticプロパティにアクセスできる。
インスタンス化してない状態でアクセスできます！

```Swift:Self.playground
class Person {
    static let raceName = "日本人"
    func sayName() {
        print("私は\(Self.raceName)です。")
    }
}
```

# selfとSelfの違いを見てみる！
理解を深めるためにPlaygroundで動かしてみてください！

```Swift:Swift.playground
class Person {
    static let raceName = "日本人"
    let name: String
    init(name: String) {
        self.name = name
    }

    func sayMyName() {
        print("私の名前は\(self.name)です。私は\(Self.raceName)です。")
        //🟩SelfはPersonに置き換え可能
        //print("私の名前は\(self.name)です。私は\(Person.raceName)です。")
    }
}
//🟥エラー：Cannot find 'hinakko' in scope
//print(hinakko.name)
print(Person.raceName)//日本人


func f() {
    let hinakko = Person(name: "ひなっこ")
    hinakko.sayMyName()//私の名前はひなっこです。私は日本人です
    print(hinakko.name)//ひなっこ
    print(Person.raceName)//日本人
}

f()
```
Playgroundで動かしてみると、
🟥エラー：Cannot find 'hinakko' in scopeの下のprint(hinakko.name)でエラーが起こります！
インスタンス化されていないため、エラーになります！
一つ下のprint(Person.raceName)は型に紐づいているため、正常にprintされます。

そのため、sayMyNameメソッドのprint("私の名前は\(self.name)です。私は\(Self.raceName)です。")
🟩Selfは型自身にアクセスするため、Personに置き換え可能
❌selfはインスタンス自身にアクセスするので、Personに置き換えは不可

# 参考文献
https://gihyo.jp/book/2020/978-4-297-11213-4
re:Invent 2023 出張記 Part1

# re:Invent2023 出張記 Part1
この記事では、英語を喋れないSEが初めてre:Inventに参加する様子を記載します。

re:Invent行ってみたいけどどんな感じか分からない、英語喋れない、アメリカ怖い…と感じてる筆者の様な方の助けになれば幸いです。

因みに、筆者はre:Inventだけでなく、アメリカも初めてです。そういった部分も含め記載していくので、暖かい目で見て頂ければと思います🙇

## 申し込み
筆者は近畿日本ツーリストさんが主催する[AWS re:Invent 2023 Japan Tour](https://knt.reinventjapantour.com/)を申し込みました。re:Invent2023の申込者数約38,000人に対して、日本人が約1,600名いるようなのですが、1,600名の内600名の方がこのツアー申し込んでいるようです。

因みに、このツアーには以下が含まれています。
- 往復の飛行機
- ホテル
- 空港とホテルの往復バス

一方で、re:Inventのチケットは含まれていないので、ツアーとは別に自分でre:Inventへの申込みが必要です。

また、追加料金を支払うことで、以下のサービスが受けられます。必要に応じて申し込まれると良いと思います。
- ESTA代理申請
- 海外旅行保険

## 準備
準備としては、以下があるかと思います。これらについて、簡単に記載していきます。
- 荷物
- セッション予約
- モチベーション

### 荷物
持ち物の準備ですが、[こちらの記事](https://dev.classmethod.jp/articles/aws-reinvent-2023-mochimonolist/)を参考にさせて頂きました。

プラスで必要と感じたものなどあれば、イベント終了後の記事で記載したいと思います。

### セッション予約
re:Inventのマイページで、セッションの予約を行うことができます。セッションの予約開始は、日本時間だと夜中に開始されます。人気のセッションはすぐ埋まってしまうので、人気のセッションを狙いたい場合は夜中待機が必要になります。

このセッション予約サイトですが、英語のみで非常に重たいです…
セッションがあるはずなのに、セッションがありませんと出たりもするので、寛大な心で挑んで下さい。

主なセッションタイプの概要は以下の通りです。
| セッションタイプ | 説明 |
|---|---|
| Keynote | 基調講演、予約不要 |
| Innovation Talk | 最新の技術やビジネス情報についての講義 |
| Breakout Session | 一般的な講義形式 |
| Builders Session | 手を動かす形式の講義で、AWSエキスパートがグループについてくれる |
| Boot Camp | 長時間の手を動かすトレーニング |
| Chalk Talk | テーマについて講師から説明があり、講師や参加者で議論する形式 |
| Code Talk | 実際の環境をデプロイするなどのデモを見ながら、講師や参加者で議論する形式 | 
| Workshop | 手を動かすトレーニング |
| Lightning Talk | その名の通り20分程度のLT、予約不要 |
| Spotlight Lab | 特定のサービスや機能について学習し、講師に質問ができる形式 |
| Gamified Learning | ゲーム形式で課題や問題に取り組む形式 |

その外にも、自己学習のためのSelf-paced Labや卓球大会などのCommunity Activies、授乳室などのConference Servicesがあります。

### モチベーション
re:Inventが楽しみな気持ちと同じくらい、英語が喋れないことへの不安とアメリカという国への不安があります。

しかし、ツアー代とイベント参加費だけで約100万円程するということもあり、申し込んでしまえば、楽しむしかない、何か持ち帰るしかない、という気持ちがたかぶって来ますので、時間が解決してくれることでしょう！
#筆者はそう言い聞かせた

## スケジュール
申し込むツアーのコースによってスケジュールが異なりますが、筆者はベーシックプランを申込ました。

ベーシックプランの簡単なスケジュールは以下の通りです。
| 日付 | 時間 | アクション |
|---|---|---|
|11月26日(日本)|昼頃|空港集合|
||夕方|日本発|
|11月26日(米国)|朝|ロサンゼルス着|
||夕方|ロサンゼルス|
||夕方|ラスベガス着|
|11月27日(米国)|終日|re:Invent参加|
|11月28日(米国)|終日|re:Invent参加|
|11月29日(米国)|終日|re:Invent参加|
|11月30日(米国)|終日|re:Invent参加|
|12月1日(米国)|早朝|ラスベガス発|
||昼頃|ロサンゼルス着|
||夕方|ロサンゼルス発|
|12月2日(日本)|夕方|日本着|

この他にも、アーリープランだと1日早く現地に到着出来たり、フルエントリープランだと1日長く現地に居れたりします。

## 最後に
今後、実際に行ってみた感想などをタイムリーにあげていきたいと思っています。

アップデートの内容などは某会社さんのブログが早くて詳細に記載されていると思います笑

そのため、この旅行記ではそういった部分とは別の視点でのre:Inventをお伝えできたらと思っていますので、よろしくお願いします！

## 出張記リンク

https://qiita.com/y_sekine/items/c0b2c262a434b71abe20

https://qiita.com/y_sekine/items/ce95339edee0c496c796

https://qiita.com/y_sekine/items/d36d797a05e0f305b8ba

https://qiita.com/y_sekine/items/bd07ccd6e2742d6639f8

https://qiita.com/y_sekine/items/f82c4204daf0c871f582

https://qiita.com/y_sekine/items/e985cf0478dd27ac86f4

# We Are Hiring!

https://www.biprogy.com/recruit/recruiting/
ストレージの制限　STORAGE_LIMIT_EXCEEDED

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)



# There was an unexpected error in your org which is preventing this assessment check from completing: System.DmlException: Insert failed. First exception on row 0; first error: STORAGE_LIMIT_EXCEEDED, storage limit exceeded: []

+ [Create initial Submission Actions Error Message](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007RdQrd)

:::note
You can delete records to free up space.
But I think it's easiest to use a new playground.

Option #2 Delete Files or Records

If you are budget-conscious and would rather go for storage usage reduction than purchasing extra storage, you can: • Find and delete outdated leads • Find and delete outdated contacts • Delete files in Salesforce CRM Content • Remove unnecessary attachments This might seem simple at first glance, but it is not! Knowing what is outdated and unnecessary is not an easy task. Another option, in the case of file storage, is to move the files elsewhere. Let’s look into that option in the next section.

Salesforce Storage Limit Exceeded: How to Overcome this Costly Challenge
https://www.connecting-software.com/blog/salesforce-storage-limit-exceeded/

レコードを削除してスペースを解放できます。
でも、新しい遊び場を使うのが一番簡単だと思います。

オプション #2 ファイルまたはレコードを削除する

予算を重視しており、追加のストレージを購入するよりもストレージ使用量の削減を希望する場合は、次のことが可能です。 • 古いリードを検索して削除する • 古い取引先責任者を検索して削除する • Salesforce CRM Content 内のファイルを削除する • 不要な添付ファイルを削除する これは簡単に思えるかもしれませんが、一見するとそうではありません！何が時代遅れで不必要かを知るのは簡単な作業ではありません。ファイル ストレージの場合のもう 1 つのオプションは、ファイルを別の場所に移動することです。次のセクションでそのオプションを見てみましょう。
:::

+ [Salesforce のストレージ制限を超過: このコストのかかる課題を克服する方法](https://qiita.com/Keiji_otsubo/items/04cc3c241b35c8465484)

# その他

+ [Is it possible to set a file storage limit per user? Or is the limit just for the org?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007eoupC)

:::note
There are no user limits. The only correlation between user and storage limits is the number of users are used to allocate additional storage.

https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A902ISAR
:::

+ [ファイルストレージ容量の計算について](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000nqxE)
WindowsでのRPi.GPIOを使った開発

# RPi.GPIO
ラズパイのGPIOを利用するPythonのライブラリ．ラズパイでGPIOを操作するPythonコードは半分以上はこれを利用している気がする．

Chat-GPTにLチカのコードを書かせても以下のプログラムが出てくるのでこれが一般的だと思われる．ラズパイでGPIOを利用したことがある人は一度は見たことがあるはず．

```python
from RPi import GPIO
import time

# ピン番号の設定
led_pin = 18

# GPIOの初期化
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)

# Lチカの実行
try:
    while True:
        GPIO.output(led_pin, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(led_pin, GPIO.LOW)
        time.sleep(1)
except KeyboardInterrupt:
    GPIO.cleanup()
```

ただ，RPi.GPIOはWindowsにはインストールできないので
+ コードがWindows上で実行できない（GPIO以外のバグも探すのが困難）
+ ライブラリがPC上にないのでサジェスチョンも使えない

などの開発を阻害する問題が発生する．

ラズパイ上にファイルサーバを走らせて，VSコードでラズパイ上のpythonをインタープリターとして選択するという裏技はあったがラズパイの電源を入れて接続した状態じゃないと使えないのでこれもめんどくさかった．

# fake_rpi
WindowsでRPi.GPIOみたいにググってもいい解決法が出てこないので半ばあきらめていたが，Windowsでも動作確認までできるライブラリがひそかに作られていることを偶然発見．それが```fake_rpi```．自作もできはするがめんどくさい何とも痒い所に手が届くライブラリではないだろうか．

pipでインストールするだけで使えるので大変便利
``` terminal
pip install fake_rpi
```

使い方も非常に簡単で```RPi```の前に```fake_rpi```を付けるのみでOK．
（ドキュメントでは名前空間の置き換えをするようになっているがimport文にちょっと足すほうがシンプルでわかりやすいような気がしたのでこの方法で書いている．）

``` diff_python
- from RPi import GPIO
+ from fake_rpi.RPi import GPIO
import time

# ピン番号の設定
led_pin = 18

# GPIOの初期化
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_pin, GPIO.OUT)

# Lチカの実行
try:
    while True:
        GPIO.output(led_pin, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(led_pin, GPIO.LOW)
        time.sleep(1)
except KeyboardInterrupt:
    GPIO.cleanup()
```

これだけでコードのサジェスチョンも使えるようになる．
![スクリーンショット 2023-11-27 041700.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494165/63a829dc-05a3-f831-a5ff-d992b202abcd.png)

また，実行時にGPIO操作のlogまで出してくれる．なんと便利なこと
```
fake_rpi.RPi._GPIO.setmode(11,)
fake_rpi.RPi._GPIO.setup(18, 0)
fake_rpi.RPi._GPIO.output(18, 1)
fake_rpi.RPi._GPIO.output(18, 0)
fake_rpi.RPi._GPIO.output(18, 1)
fake_rpi.RPi._GPIO.output(18, 0)
fake_rpi.RPi._GPIO.cleanup()
```
ちなみにこのログが不要であれば
```python
from fake_rpi import toggle_print
toggle_print(False)
```
でなくすことができる

# 最後に
このライブラリを開発した方には大変感謝するとともにもっと普及してほしい．．．（もう少しで自作してしまうところだった．）

RPi.GPIO以外にsmbusなども実装されているようなので詳しくはドキュメントを参考に

実用上は
```python
try:
    import RPi.GPIO as GPIO
except ImportError:
    from fake_rpi.RPi import GPIO
```
とでも書いておけば完ぺきではなかろうか

# 参考文献
https://pypi.org/project/fake-rpi/

https://github.com/MomsFriendlyRobotCompany/fake_rpi
ETFを１００万投資した時の１０年後の金額は？

前回はYahooファイナンスのAPIを使って年利を出すコードを書いたが、
今回は実際に１００万円入金したら１０年後にいくらになるか計算するプログラムを書いたよ！
NISAの投資に役立ててね！

```python
# 初期投資額
initial_investment = 1000000  # 100万円

# VYMとVTIの想定年間リターン率
annual_return_vym = 0.05  # 5%
annual_return_vti = 0.07  # 7%

# 投資期間（年）
years = 10

# VYMとVTIの平均配当利回り
dividend_yield_vym = 0.0328  # 3.28%
dividend_yield_vti = 0.0142  # 1.42%

# 年間総リターン率（価格上昇＋配当）
total_annual_return_vym = annual_return_vym + dividend_yield_vym
total_annual_return_vti = annual_return_vti + dividend_yield_vti

# 配当再投資を含む複利計算
final_amount_vym_dividends = initial_investment* (1 + total_annual_return_vym) ** years
final_amount_vti_dividends = initial_investment * (1 + total_annual_return_vti) ** years

# 各ETFの10年後の総額（配当再投資含む）
print("VYM:"+str(final_amount_vym_dividends)+"円")
print("VTI:"+str(final_amount_vti_dividends)+"円")

```

出力例
VYM:2215554.670181221円
VTI:2244367.80105035円
2023/11/27主にITとかセキュリティの記事

サイバー攻撃の標的となる各組織の「隙」が、ダークウェブの「地下フォーラム」で情報交換されている(11/25)
https://www.newsweekjapan.jp/kumar/2023/11/post-4.php

またもや狙われた百万都市　サイバー攻撃に遭ってから発表までの時間が長過ぎる(11/24)
https://kn.itmedia.co.jp/kn/articles/2311/24/news058.html

パスワードはあえてオフラインで作成！画期的な生成ツール「PassCard」(11/25)
https://gunosy.com/articles/e5Oaf

AIが人生の会話のすべてを記録していく未来とは(11/25)
https://wired.jp/article/the-case-for-using-ai-to-log-your-every-living-moment/

グーグル、教育機関向けセキュリティガイドブックを公開(11/25)
https://news.yahoo.co.jp/articles/7c6ad353befcb21e7725216227b2443d4b922b17?source=rss

ランサムウェア「LockBit 3.0」がCitrixの脆弱性悪用して攻撃、CISAが警戒発表(11/25)
https://news.mynavi.jp/techplus/article/20231125-2825229/

国内メーカー製ルータとネットワークビデオレコーダに脆弱性、注意を(11/24)
https://news.mynavi.jp/techplus/article/20231124-2826370/

Windows Helloの指紋認証センサーに脆弱性、ノートPCの認証バイパスに成功(11/25)
https://news.mynavi.jp/techplus/article/20231125-2826101/

GoogleのセッションCookieを復元できると主張するマルウェア発見(11/24)
https://news.mynavi.jp/techplus/article/20231124-2826378/

FirefoxとThunderbirdに脆弱性、更新プログラムの適用を(11/25)
https://gunosy.com/articles/e2Ltr

Adobe ColdFusionの緊急脆弱性、CISAが更新を勧告(11/25)
https://news.mynavi.jp/techplus/article/20231125-2826113/

Linuxのランサムウェアは捉えどころなく検出困難、Windowsには歴史あり(11/24)
https://news.mynavi.jp/techplus/article/20231124-2825225/
私の、ニュートラルポジション！


リンクラフト**アドベントカレンダー**の**１１日目**！！
エンジニア歴3年目、元柔整師のAINAです！！

前職からエンジニアに転職し、自分自身を見つけ直す機会がありました。
皆さんは、自分を見つけ直すと言う経験をしたことはありますか？

と言うことで、エンジニア歴の浅い私は技術以外の私が毎日大切にしていること！
私の「**ニュートラルポジション**」について少し書こうと思います。

ニュートラルポジションってなに？？って思いますよね！
私の恩師が教えてくださった言葉で、明確に意味があるものではないですし時々で色々な意味があります。
ここでは、ブレないもの・自分自信の柱と言ったような忘れてはいけないものと意味で書かせてもらいます。

「人生はゲームそのもの！」
-----
※あっ私はゲーマーではないです！！！！

私はエンジニアに転職してから、RPGゲームにハマるような感覚で毎日を過ごしていることに気が付きました。
だから「**人生はゲームそのもの！**」!

仕事でも、生活の中のことでも…
なんでも出来るようになればレベルアップし更に出来ることが**増える**！
レベルアップさせるからこそ、新しいことに挑戦できる！
その手段方法に正解はなく、不正解もない！
まさに**RPGゲーム**ですよね！！
だからエラーから抜け出せなくても、失敗しても…何があっても、毎日が楽しくて楽しくてたまらないです！

子供の頃を振り返ってみると、子供の頃はこの感覚が当たり前だったのに社会人になって見失いかけていた自分がいたんだなとすごく感じています。
後悔しても過去は変えられないですがエンジニアに転職して、このことに気がつけた私は幸せ者だなあと今は感じています！

皆さんはどのようにしてモチベーションを上げていますか？

後は、オンオフの切り替え！
-----
転職してからは今まで以上に長期休みや有給を取得しやすくなり、全力でオンオフを楽しんでいます！
「休み」といっても１日休暇だけではなく、数時間の早上がりや午後休暇をとって舞台を見にいったり、春は夜桜を見にいったり、週末の混雑を避けるための移動時間にあて**推し活**を楽しんだりしています！

最近は、「推し活休み」という福利厚生を完備している会社さんもある様で…日本全体的に休みを取りやすい環境が増えていくことを全力で願っています！

休暇以外でも、オンオフは人それぞれ方法はさまざまかと思います！
実際に私も、お風呂に頭まで潜りブクブクして頭をリセットすると言うきっと独特の方法をしたりしています！ww
皆さんの変わったリセット方法も知りたいですね！
こう言った話ができるようになったのも変化が求められている時代だからこそですね…
色々なことが理解され、私だけではなくみんなが仕事や生活が楽しいと思える時代になるよう今自分にできることをやって行きたいです！

-----

皆さんの「**ニュートラルポジション**」は何ですか？
今年も残り少し！年末年始に向け忙しい季節ですが、
少し自分自身を見つけ直し新しい一年の始まりを迎えましょう！

------------
**一緒に働く仲間を募集中です！**
リンクラフト株式会社では、組織拡大に伴い積極的な採用活動を行っています。
少しでも興味がある方はぜひご連絡ください。
▽会社ホームページ
https://lincraft.co.jp/
▽Instagram
https://www.instagram.com/lincraft.inc/
▽ご応募はこちらより
https://lincraft.co.jp/recruit
※カジュアル面談も受付中です。ご希望の方はHPのお問い合わせフォームよりご連絡ください。
ReactのFragmentとは

## Fragmentとは
Reactの __Fragment__ は、__複数の要素をグループ化するため__ に使用される特別なコンポーネントです。Reactでは、通常、コンポーネントから複数の要素を返す場合には、それらを何らかの親要素（例えばdivタグ）でラップする必要があります。しかし、この方法は時に不必要なDOMノードを追加し、マークアップを複雑にしてしまう可能性があります。Fragmentは、このような問題を解決するために利用されます。

## 主な利点
### 余分なDOMノードを追加せずに要素をグループ化：
Fragmentを使用することで、余分なノードをDOMに挿入することなく、複数の要素をグループ化できます。これにより、DOMの構造がシンプルに保たれ、読み込みパフォーマンスが向上する可能性があります。

### コードの整理：
Fragmentを利用することで、不必要なマークアップを避け、コードの可読性を高めることができます。

## 使用例
~~~jsx
import React, { Fragment } from 'react';

function MyComponent() {
  return (
    <Fragment>
      <h1>タイトル</h1>
      <p>これはパラグラフです。</p>
    </Fragment>
  );
}
~~~
この例では、__Fragment__ を使用して、__h1__ タグと __p__ タグをグループ化しています。この方法により、これらの要素は直接親コンポーネントに挿入され、余分な __div__ などの要素の追加を避けることができます。
DockerでスリムなJREとMinecraftする

## Docker ってなんや
とりあえずいろいろ動くVM
LinuxだけでもなくOSから対応CPUからいろいろある

Dockerfile がmakeファイル的な位置
いろいろそろったimageファイルにデータなどを突っ込んで、あとは実行するだけにしておく
手順はキャッシュされるので同じ手順では再利用されるっぽい
image がまとめたLinuxっぽいイメージファイル 1イメージ 1アプリ 1VM的なきまり?
imageをもとにDockerfile で積み重ねることもできる
docker-compose.yaml がそれをまとめて実行する、仮想ネットワークもあるよ
app,Web,DBなど数個まとめてあと環境変数など少々追加する

image から実行すると container が作られる、一般的なファイルシステム的なものにVMを合わせた感じか

## データはどうするの
VMではない親からファイルをマウントして使う、のが一般的な感じか
他の手段で突っ込んでもいいが、VMは割と短命なこともあるので親システムのファイルなどで置いておくのがよく使われる手法

## インストール

公式にいろいろまとまっているので簡単
Windows, RaspberryPi, CentOS Stream などに入れてみた

RaspberryPi では
```
$ curl -fsSL https://get.docker.com -o get-docker.sh
# sh ./get-docker.sh
# systemctl start docker
# systemctl enable docker
```
たぶんこんなかんじ
docker-compose というコマンドを使っているのをよくみるが、最新は docker compose だったりするよ

## Minecraft Serverか何か作ってみる

フォルダを作る
```
$ mkdir minecraft
```

中に Dockerfile を作る
```
FROM eclipse-temurin:17 as jre-build
RUN jlink \
    --add-modules java.management,java.naming,java.desktop,jdk.zipfs \
    --no-man-pages \
    --no-header-files \
    --compress=2 \
    --output /javaruntime

FROM debian:buster-slim
ENV JAVA_HOME=/opt/java/openjdk
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=jre-build /javaruntime $JAVA_HOME
RUN mkdir /opt/app
ENV EULA true
ADD https://piston-data.mojang.com/v1/objects/5b868151bd02b41319f54c8d4061b8cae84e665c/server.jar /opt/app/server.jar
WORKDIR /opt/app
RUN ["java", "-Xmx2048M", "-jar", "/opt/app/server.jar", "nogui"]
RUN echo eula=$EULA > /opt/app/eula.txt
CMD ["java", "-Xmx2048M", "-jar", "/opt/app/server.jar", "nogui"]
EXPOSE 25565
```
docker-compose.yaml も作る
```
version '3'
services:
  mcserver:
    build: .
    volumes:
      - ./world:/opt/app/world
    ports:
      - '25565:25565'
```
とりあえずこれだけ。フォルダの中で
```
docker compose up
docker compose up -d
```
で実行 -d をつけるとデーモンとして裏で動くことになる
付けないと Ctrl - C でも止まるが止まるのは mcserverの部分だけなのでどちらの場合でも
```
docker compose down
```
で仮想ネットワークなども停止しよう
```
docker compose stop
docker compose start
```
でなんとなく一時停止的なもの
実行中のcomponentが残るか消えるのかの違いがある。
消えても docker-compose.yaml で指定した world のデータは残るので Minecraft はどっちでもいいよということになる。
コンポーネントを残すなら消してしまえ、というのでいいかもしれない。

## Dockerfile の解説
1行目のFROM から 次の FROM まではいきなり特殊なことをしている
JDKなimageからJREを作る、という1つめの環境。jre-build と名付けられているらしい。必要なmoduleの調べ方はまた別のおなはし。
2つめのFROM は 最小Linuxっぽいところを使う宣言
ENVで環境変数を設定してCOPY でJREを元のjre-buildの環境からコピーする
1つめのjre-build 環境は捨てられるので出来上がりのimageはコンパクトになる。
RUN mkdir /opt/app からが Minecraft 環境づくり。手前をばっさり切って
```
FROM eclipse-temurin:17-jre
```
としてもいいし21でもいいがimageファイルのサイズはふくらむ。
Minecraft の server.jar この場合は1.20.2 を https://www.minecraft.net/ja-jp/download/server から取ってきて、1回実行して必要なファイルを吐き出させてみた。ライセンス承認の書き込みをしてここまででimageファイルになる。
最後のCMD行は実行用。
EXPOSEは使用するポート番号。

## docker-compose.yaml の解説
こちらは単純
よく知らないがバージョンがあり
サービスとして mcserver という名を付けたものを動かすよ
普通なら web とか db とか tomcat とか名付けて分けるがここでは1つ
image はどこ、ということで build: . としておけば その場にある Dockerfile を使って初回に image を作る。あらかじめ image がある場合はそれをimage: で指定するだけ。
あとはフォルダとポートを適当に指定する。フォルダは親側のファイルが反映される。親側になければ作られる。VM側にファイルがあっても見えなくなる。
ポートは仮想ネットワーク上のものを親側のポートとして見えるようにする。Dockerfile側でEXPOSE指定してあるもの。同じ番号で繋ぐ必要はない。
大学入試問題をpythonで解く


```math
連立方程式|x|+|y|-2>=0 x^2+2x-2y-1>=0を表す領域をDと領域Dを平面座標に表示してその面積を求めよ


```
```python

from sympy import *
from sympy.abc import *
import numpy as np
import matplotlib.pyplot as plt
x1=np.linspace(0,3)
x2=np.linspace(0,3)
x3=np.linspace(-3,0)
x4=np.linspace(-3,0)
x5=np.linspace(-3,3)
print(x1)
y1=-x1+2
y2=x2-2
y3=-(-x3-2)
y4=-x4-2

y5=(x5*x5+2*x5-1)/2
plt.ylim(-3,3)
plt.grid()
plt.plot(x1,y1)
plt.plot(x2,y2)
plt.plot(x3,y3)
plt.plot(x4,y4)
plt.plot(x5,y5)

```
![rei48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354057/c7bce267-27b4-d44e-2ce2-1b161ebc64e9.png)
CSSでテキストが1行のときは中央揃えで複数行のときは左揃えにするテクニック

## はじめに

https://x.com/takamosoo/status/1728649201993859215

@takamoso さんという方のツイートが自分のTwitterに流れてきて、面白い手法だなとは思ったのですが、コンテナクエリが全ブラウザで対応な現在、わかりやすくできないかと思い、コンテナクエリを利用したやり方のご紹介です。

## コンテナクエリを利用したやり方

https://coliss.com/articles/build-websites/operation/css/about-css-container-queries.html

コンテナ幅によってスタイルを変えられるというめちゃくちゃすぐれたCSSのプロパティです。コンテナ幅が500px未満だったらそのコンテナ内だけテキストを赤にするなど設定することも可能です。

以下が自分の実装したやり方です


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


まず、`container: layout / inline-size;`で.containerクラスに対して`container`の設定をしてあげます。layoutは`container-name`で、`inline-size`は横方向のサイズで判定ということです。

そしてmax-widthを設定してあげます。そのmax-widthの値が、コンテナクエリで判定するブレークポイントとなります。


次に.containerクラスの中のpタグです。そのままだとwidthが.containerクラスと同じになってしまうので、`width:fit-content;`で幅を文字列の幅にしてしまいましょう。こうすると、今度は`text-align`が効かなくなります。幅が文字列と同じ幅なのでそうなりますね。`margin-left`と`margin-right`で`auto`を設定するやり方で、中央寄せにします。


そして最後に、コンテナクエリをつけます。500px以上の時はmargin-leftを0にすれば左寄せになるので、
```css
@container layout (min-width: 500px;) {
  p {
    margin-left:0;
  }
}
```
となります。
以上のやり方で、テキストが1行のときは中央揃えで複数行のときは左揃えにしてみました。

@containerが実装される前まではtakamosoさんのやり方が良さそうでしたが、そのやり方はちょっとテクニカルすぎるかなと思いました。@containerを使ったやり方のほうが直感的に扱えるなと感じました。

コンテナクエリは全ブラウザに対応したので、ぜひじゃんじゃん利用してみましょう。

あと、こちらの方の記事も興味深かったのでご紹介です。

https://kojika17.com/2023/03/css-container-queries-swamp.html
【Rails】text_fieldにカンマ入り金額が入力され1円で出品されそうになった話

## 経緯
ECサイトにシステムから1800ドルで出品する処理を行ったところ1ドルで出品されるという報告を受ける。
⇨検証のため同じ環境で同じ価格で出品したところ、正常に出品される。
⇨原因がわからない。
という事象が発生。

## 原因
出品テストの担当に聞いたところ1800ドルが1ドル、2200ドルが2ドルになっているとのこと。
ここで「入力値にカンマやピリオドが入っているのでは」と気付く。

入力欄を確認するとnumber_fieldではなくtext_fieldとなっており、
価格を1,800ドルで出品してみると、1ドルで出品される現象が再現された。

## いろいろ確認してみた
今回の対処としてはtext_fieldをnumber_fieldに修正し、
数字以外入力不可能とすることで完了したが、
int型,decimal型で文字列を含む数字を受け取った時の挙動を確認してみた。

1,000　→ 1
1,000円　→ 1
10,000 → 10
¥10,000 → 0
いちまんえん → 0

先頭から文字列までの数値が保存されるようだ。

## まとめ
価格、数量など数値しか扱わない部分はnumber_fieldを使いましょう。
初歩的すぎかもしれませんが、「1500ドルが1ドル、2200ドルが2ドルになっている」の情報がなかったら
たぶんもっと気付くのに時間がかかってたと思うので戒めも含めて書き記します。


## 追記
number_fieldにすると小数点も弾かれてしまうので、
オプションでstep:を追加するのを忘れずに
```ruby:view.slim
= f.number_field :selling_price,
  class: 'form-control',
  min: 0,
  step: 0.01,
  required: true
```
【GitHub】organization内でPull Requestの承認先をCODEOWNERSを使用し制御する方法

# 背景
GitHubのorganizationの運用について検討していました。
developブランチからmainブランチへPRを作成する際に、
特定の人にPRの内容をレビューして頂きたい事があり、本記事はその方法について調べたものです。

# 対象の方
- GitHubのorganizationの運用について考えられている方
- タイトルに興味を持った方

# やりたい事
PRのレビューをされる方を制御したいです。
GitHubのCODEOWNERSを使えば、PRが作成された際に指定したチームの方にレビューのリクエストが届くようにできそうでした。

https://docs.github.com/ja/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners

# 方法

### 1. organization内にリポジトリを作成

### 2. Branch protection ruleの設定
今回は以下のように設定しました。
Code ownerからのレビューを通らないとマージできないようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/97d6da32-e685-2fb0-5cb2-442ea2dd97a3.png)

### 3. リポジトリに招待するチームの作成
以下の2チームを作成し、どちらともwrite権限を割り当ててリポジトリに招待しました。
- ソースコードを変更し、PRを作成する役割のチーム
- PRをレビューする役割のチーム

チームを作成した時の設定は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/c4ba7ac3-47f1-fcbb-7fed-9605fcb28e7f.png)

この際、PRを承認する役割のチームのCode reviewタブから以下のように設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/461ef8ea-baa4-3b68-82f9-ec9563a9655b.png)

### 4. CODEOWNERSファイルの作成 
`CODEOWNERS`ファイルを`.github/`の直下に作成しました。
`CODEOWNERS`に記載した内容は以下の通りです。

```:.github/CODEOWNERS
* @testHogeOrganization/testTeam 
```
### 5. プルリクの作成
developブランチに更新を加え、mainブランチへPRを作成しました。
承認者チームにレビューのリクエストとメールが届いておりました。

# 参考
- https://docs.github.com/ja/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
- https://qiita.com/FumiyaShibusawa/items/c7a3ff4d0793ca2d281f
ISUCON13 振り返り

# 総括
来年もっと精進してもう一回リベンジするぞ。

詳しい、解放についての考察等は、別途します。
とりあえず、やってみての感想。
# 振り返り
## Keep
- isucon本で勉強したことは、当日しっかりできた。
- 当日楽しみながらできた。
## Problem
- isucon本攻略をしっかり進めれば、もっとスコア出たはず。
- GoでのWebアプリケーションの経験が0だった。
- debugスキルが皆無だった。
- 過去問を解いてチームで予行練習をしておけばよかった。
    - 特にssh周りなどで結構躓いた。
- 生のLinuxサーバーでの開発経験が少なかった。
- gitを上手く使えなかった。
    - addに時間がかかりすぎるという理由で、使うのをやめた。
- 利用している技術がなんなのか。どのような役割をしているのか？などをなんとなくでしかわかっていなかった。（DNSやnginx等）
## Try
- isucon本を読み、isucon本の内容について一通り説明できるようになっておく。
- Linuxサーバーでの開発経験を増やす。
# 当日の感想
普段の開発環境ががサーバーレス・コンテナ開発に偏りすぎているため、コンテナを使わないLinuxのサーバーを使った開発力が低かったと痛感。
GoでのWebアプリケーションの開発経験がなかったため、動いている今のものを下手に弄ることでスコアが下がると嫌だ。という感情が強かったのがよくなかった。
gitも上手く使えずに、とりあえず直にサーバーを修正すればええやろ。（絶対業務ではしないが）といったノリで進めてしまったのが良くなかった。
普段業務でウェブアプリケーション開発をしていない分、過去問などを通じて精進をするべきだった。
# 細かい反省
## 開発UX観点
### code deployフローの整備
直接Linuxサーバーで作業をしたため、普段の自分がやり易い環境を活用し切ることができなかった。
スコアに直結しそうな改善をし、PRを作りMainにマージしたらサーバーにdeployされてベンチマーカーを回す。
この一連のサイクルを回せるともっと開発が楽で楽しかっただろうなと思った。
### gitの活用
`git add .`が時間かかりすぎて、途中でgitを使うよりとりあえず作業を進める。という方針にしてしまった。
これによって、確かにスコアが上がったけど...何がよかったの？というのがわからなくなった。
チーム内での作業の振り返りも『なんとなくこんなことやってたなぁ』になってしまったのは、よくなかった。
作業ログを残すためにも『gitをなんとでも導入するよ。』というのは、チーム内で決めておけばよかった。
### やることリストを作る
始まったらやるべきことの共有などができていなかった。
どんな問題であったとしても共通でできることがあるはずなので、そういったことをまずパパッとやる。といったやるべきことリストを作っておくと当日の午前中がもっと有意義になったはず。
## 開発観点
### 自信を持ってる言語がなかった
なんの言語でもいいが、『自信を持って高速化できます！任せてください！』と言える言語がなかったことで、アプリケーション自体の修正に手を出すことができなかった。
特定のhttpリクエストで失敗していることまでわかり、どこの関数を修正すればいいかまで見えたが具体どうすればいいかの解決策を提示できなかった。
どんな言語でもいいから、『Webアプリケーション作れます。』『同時アクセス数が多くても行けます。』みたいに自信を持った状態にしておくべきだった。

最近はPythonばかり書いているが、WEBアプリケーション開発はしていないので、やはりGolangを勉強するのが良さそうだなという感想。
### ミドルウェアの理解が甘かった
nginxやDNSについて、理解がなんとなくしかできていなかった。
課題に対してなぜこの施策が有効なのか？を説明した上で、施策のの具体的なconfig設定まで出来る理解力がなかった。
# 当日のスコアの推移
途中ベンチを動かせない時間があったりしたが、地道に少しずつ伸ばした感じです。
最終的には、6000点オーバーにすることはできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431977/87e879bb-62d5-7735-8bc1-533ab427c534.png)

# 最後に
isuconみたいなWebアプリケーションのパフォーマンスチューニングは業務では必要にはならない。
だからこそisuconに参加して今までの業務で触れなかった世界に触れたのはよかった。

僕のやりたいこと的に今後パフォーマンスチューニングが必要な業務に従事するか？でいうと多分No。
だけど、課題があるシステム構成に対して施策を考察して、考察した結果を実装し、ベンチマーカーで数値改善しているか？を確認する。このフロー自体はとても好き。
趣味として今後もやりたい。

AtcoderやKaggleとかよりも、個人的には好きなコンテストだった！
勉強の過程で得ることができる知識が、僕にとってとても有意義だったし、楽しかった！
Linux(XDG)/Mac ディレクトリルール(場所)でモヤる件

[![tux](https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/202px-Tux.svg.png)](https://commons.wikimedia.org/wiki/File:Tux.svg)[![hmm](https://img.freepik.com/free-vector/hand-drawn-people-asking-questions-illustration_23-2148911451.jpg?w=250)](https://www.freepik.com/free-vector/hand-drawn-people-asking-questions-illustration_13379595.htm)[![apple](https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/Apple_Computer_Logo_rainbow.svg/206px-Apple_Computer_Logo_rainbow.svg.png)](https://commons.wikimedia.org/wiki/File:Apple_Computer_Logo_rainbow.svg)

(<ins>Mac</ins>ユーザー向けの記事です)
## <ins>Linux/Mac</ins> の各種ファイル場所とそれに関してコメント
| 用途       | 場所(XDGデフォルト)  | 場所(Macオリジナル) | 場所(アプリ独自？) |
|:---------:|:-----------------:|:----------------:|:-------------:|
| 設定ファイル  | `~/.config`      | `~/Library/Application Support` | |
| キャッシュ    | `~/.cache`       | `~/Library/Caches` | `~/Library/Application Support/Caches`<br>`~/Library/Application Support` |
| データファイル | `~/.local/share` | `~/Library/Application Support` | |

インストールしたソフトウェアによって各種ファイルの置き場所がバラバラでモヤります。`~/Library/Application Support`ディレクトリはGUI専用でCLIはみんなXDGに従うものと勝手に思っていましたがそうではなさそうですね……。
`~/Library/Application Support`にGUIとCLI両方のソフトウェアのファイルがあるのは(大文字と小文字が両方並んでいるのは嫌だし第一GUIとCLIは別に扱いたいので)個人的には好ましくありません。(目当てのディレクトリを探すのに時間がかかりそうです。)
XDGのディレクトリとMacオリジナルディレクトリを両方使っている中途半端なソフトウェアもありました。
そんな訳でなんとなくモヤりましたというお話しでした。

他にも似たような仕様に関するモヤることあればコメントお願いします。
内容に不備・誤りがございましたらご連絡下さい。修正致します。
<select>内に<hr>で区切り線をつける

selectタグは、ドロップダウンリストを作成するためのタグですが、見た目に工夫を加えることでユーザーエクスペリエンスを向上させることができます。

メニューバーなどで使われている区切り線を、select要素の子要素としてhrタグを含めることでwebでも表現できるようになりました。

現時点で
・Safari 17
・Chrome 119
にて実装されています。

```ruby:index.html
<select>
 <option>テスト</option>
 <option>テスト</option>
 <hr>
 <option>テスト</option>
 <option>テスト</option>
</select>
```
ブラウザの仕組み - レンダリング

# はじめに
HTML,CSS で Web サイトの見た目を作り、JavaScript で動きを出す。そして、PHP を使って MySQL などデータベースとやり取りをする仕組みを作る。
今までにこのようなことを学んできましたが、ではそれがブラウザ上で実現するために、ブラウザがどのような仕組みになっているのか。
今回は、ブラウザの仕組みについて学んだことをまとめていきます。

## ブラウザの大まかな構造
ブラウザの主な機能は、HTMLファイルや画像などのウェブリソースをサーバーにリクエストし、ブラウザウィンドウに表示することです。
リソースのある場所は、ユーザーが URI (いわゆる URL )で指定します。

ブラウザはサーバーから受け取ったHTMLやCSSの情報を解析して画面に表示するのですが、その裏側では何が起こっているのでしょうか。
まずは、大まかにブラウザ全体の構造を把握していきましょう。

ブラウザはいくつかのパーツに分けることができます。
- ユーザーインターフェース（UI）
- ブラウザエンジン
- レンダリングエンジン
- ネットワーク
- UI バックエンド
- JavaScript インタープリタ
- データストレージ

これを図に表したのが以下です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3070527/ff100c9f-8f15-522b-561d-0fab6e6124d5.png)
出典：[Web dev - ブラウザの仕組み](https://web.dev/articles/howbrowserswork?hl=ja#the_browsers_high_level_structure)

それぞれについて、簡単に解説します。

### ユーザーインターフェース（UI）
ユーザーインターフェースは、ユーザーとブラウザの接点となる部分のことです。
ブラウザの画面のうち、Web ページを表示する部分以外のすべてを指し、アドレスバーや戻るボタン、ブックマークバーなどが該当します。

### ブラウザエンジン
ブラウザエンジンは、UI とレンダリングエンジン間でデータの交換やができるようデータ形式の変換などを行います。

### レンダリングエンジン
レンダリングエンジンは、リクエストされたコンテンツを表示します。たとえば、リクエストされたコンテンツが HTML の場合、レンダリング エンジンは HTML と CSS を解析し、解析されたコンテンツを画面に表示します。

### ネットワーク
HTTPリクエストのようなネットワーク部分を担当します。

### UI バックエンド
UI バックエンドは、どのプラットフォームでも見るようなコンボボックス(記入できるドロップダウンリストのこと)やウィンドウなどの基本的なウィジェットの描画に使用されます。

### JavaScript インタープリタ
JavaScript コードを解析して実行するために使用します。

### データストレージ
Cookie など、あらゆる種類のデータをローカルに保存しなければならない場合があります。その際に使用する永続的な保存庫がデータストレージです。

今回は、これらのうち、中核をなすレンダリングエンジンの役割について詳しく見ていきます。

## レンダリングエンジン
レンダリングとは、HTML などのコードで
書かれた文書を、ルールに基づいて解析し、見た目を整えて画面に表示することをいいます。
レンダリングエンジンは、ブラウザによって異なるものが使用されています。


## レンダリングの流れ
レンダリングは、大きく分けて以下の流れで進行します。
- パース
- レンダリングツリー構築
- レイアウト
- ペインティング

### 1.パース
パース(perse) とは、解析するという意味です。HTML ファイルを上から順に読んでいき、コードを元に要素をDOMツリーに配置していきます。

#### DOM ツリーとは
DOM は、Document Object Model の頭文字をとったもので、Javascriptなどで外部操作できるようにするための定義です。
DOM ツリーは、DOM の定義を元に Web ページ上の要素の階層構造を表現したデータ構造のことです。

HTML ファイルから DOM ツリーが作られ、また、CSS ファイルからはそのCSS
 版の CSSOM(CSS Object Model)ツリーが作られます。
 
コードを解析してこれらのツリーを作成するのがパースのフェーズです。

### 2.レンダリングツリー構築
DOM ツリーと CSSOM ツリーの情報を元に、画面表示のための情報を整理したレンダリングツリーを作成します。
画面表示用なので、CSS で display: none が指定された HTML 要素などは含まれません。

### 3.レイアウト
レンダリングツリーを元に、ブラウザの画面にどのように要素を配置するかを計算するのが、レイアウトの段階です。
width: 50% などの計算を行います。

### 4.ペインティング
実際に画面に描画して表示することをペインティングといいます。

## レンダリングブロックとは
このレンダリングの過程を踏まえて、コーディングする際に注意するべき点がレンダリングブロックです。
レンダリングはパース後に行われますが、すべてパースされてからレンダリングするのではなく、パースされたものを元に逐次レンダリングを行っていきます。
その中で、CSS ファイルの読み込みが遅れている場合やJavaScript ファイルをダウンロードする場合レンダリングの開始が遅れる原因になります。

## レンダリングブロックの解消法
CSS のレンダリングブロックを解消するには、「メディアタイプ」と「メディアクエリ」を使う方法があります。
また、JavaScript のレンダリングブロックについては、JavaScript のコードを HTML 内に含めるか、JavaScript の非同期化で解消できます。非同期化の方法には async と defer の 2 つのやり方があります。
JavaScript を非同期にした場合、外部参照のJavaScript ダウンロードと並行してパースを続けることができるのです。
これらを念頭に置いてコードを書くことで、Webページの高速化に繋げることができるでしょう。

## 最後に
今回は、ブラウザの仕組み、特にレンダリングの流れについてまとめてみました。
まずは概要を掴むことが大事だと思うので簡単にまとめてみましたが、これらの理解ができたら、さらに詳しくパースの流れなどを学んでいくとよいでしょう。

参考サイト：
[Web dev - ブラウザの仕組み](https://web.dev/articles/howbrowserswork?hl=ja#the_browsers_high_level_structure)
[【図解/ブラウザの仕組み】DOMとパースとレンダリング,asyncとdeferについて](https://milestone-of-se.nesuke.com/sv-basic/web-tech-basic/html-javascript-dom-parse-rendering/)
【JavaScript】文字数カウント

## `length`

文字列を単純に`length`でカウントすると結果は文字コードの数の合計となります。

```js
'あ'.length // 1
'𩸽'.length // 2
'👨‍👩‍👧‍👦'.length // 11
```

`𩸽`のようなサロゲートペア文字や、`👨‍👩‍👧‍👦`のような連結された絵文字は正確にカウントできません。

## 文字単位でカウントする

以下のようにすることで文字単位でカウントできます。

```ts
function countCharacters(str: string) {
  const characterCount = [...str].length
  return characterCount
}

countCharacters('あ') // 1
countCharacters('𩸽') // 1
countCharacters('👨‍👩‍👧‍👦') // 7
```

上記のようにサロゲートペア文字が文字単位でカウントされます。
`👨‍👩‍👧‍👦`は`['👨', '‍', '👩', '‍', '👧', '‍', '👦']`のように分割されてカウントされます。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length#examples:~:text=Since%20length%20counts%20code%20units%20instead%20of%20characters%2C%20if%20you%20want%20to%20get%20the%20number%20of%20characters%2C%20you%20can%20first%20split%20the%20string%20with%20its%20iterator%2C%20which%20iterates%20by%20characters%3A

## 書記素単位でカウントする

'👨‍👩‍👧‍👦'のような絵文字も1文字としてカウントする場合には以下のようにします。

```ts
export function countGraphemes(str: string) {
  const segmenter = new Intl.Segmenter('ja-JP', { granularity: 'grapheme' })
  const graphemeSegments = segmenter.segment(str)
  const graphemeCount = Array.from(graphemeSegments).length
  return graphemeCount
}

countGraphemes('あ') // 1
countGraphemes('𩸽') // 1
countGraphemes('👨‍👩‍👧‍👦') // 1
```

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/Segmenter/segment

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/from
ISUCON13に参加してきた

### 書くこと
- 準備
- 当日
- 振り返り

### 準備
#### Gitの初期化の仕方の調整
以前はsshkeyの転送などを行なっていたが、下記をコピペするだけでclone出来るのでかなり楽になった。
`git clone https://<user>:<pat>@github.com/<organization>/<repo_name>`

#### マシンのセットアップ
環境構築を自動化するためにShellとAnsibleで環境構築を行えるよう準備した
zsh化、notify_slackのinstall、gitのuser configなど自動化

#### fgprofの導入
GoのProfilerツールを使うようにした。スコアには影響が出づらいが、関数単位としては早くなっているとかが分かるようになった。以前はスコアあまり変わらないね、というだけで変更の影響が可視化しづらい状況だった

#### Bing Chatの利用
エラーや改善点などは基本的にすぐに投げるようにしていた。
openaiのブラウザ版に比べると出力が少し遅いので課金しても良かったかも

#### Go、Serviceなどの理解
GoでQueryを書く方法、Ubuntuでのlogの出力、確認方法など
普段そもそもあまりGoを書かない上にIDEに頼ってログ出力、デバッグをしていて、毎年Ubuntuでの確認方法が分からず苦戦していたので今年は念入りに準備した

### 当日
自分の動き方
基本的には公式推奨の動き方を参考に進めた
https://speakerdeck.com/rosylilly/isucon12-shi-qian-jiang-xi?slide=22
10:00 cloud formationの立ち上げ、bench叩く
10:10 当日マニュアル、アプリマニュアルを読む、サービスを動かす
10:50 git, zsh, notify_slack, fgprofの導入, alp slow_queryをslackに出力後ログを破棄するよう調整
11:30 alp, slow_queryを元にいくつかの改善点を考えて作業を分担
11:40 goのinstall、初期設定。 go1.21を使えというエラーが出ていたがubuntuでversion指定なしでinstallすると1.18が入ってしまい、リンクを探すのに苦労
12:20 `api/livestream/:livestream_id/livecomment` の改善に着手,fgprofを元にfillUserResponseで時間がかかっていたので着手、2度引きしている箇所を一度で取れるように。fgprof上ではfillUserResponseはかなり早くなった
12:40 次に時間がかかっている関数が `fillLivestreamResponse` 。N+1問題が入っていた為改善しようとしたがBenchが止まって影響が確認出来ず。14:50頃に再開したが失敗していたのでrevert
13:40 DBのデータが文字化けしてしまい原因調査。bashからzshに切り替えた際に UTF-8の設定が外れていたのが原因。またGitHubに書かれていたデータの初期化のコメントでcat xxx があったがcatが行数まで出力していた為エラーを吐いていたところで詰まる
15:00 アプリ,DBの2台構成の作業。bind addressを消してdb serverの向き先をprivateIPに指定して完了、と思ったら権限エラーが。Bing Chatで確認した所DB側で設定が必要とのこと。過去の設定では一度もしたことがなかったので戸惑いながら作業してようやく接続
16:00 使用されているDBがisudnsとisupipeの二つだったのでAPP, DB, DB編成にしようという話に。PowerDNSの設定がenv.shで行われているものと思い設定を変えてみたが変わらず。権限の問題で弾かれているという仮説を立てて調査していたが何もわからず。最終的にapp, app, DBの構成にした。だが appの向きがそれぞれローカルのisudnsを見ている為、スコアが下がってしまった
### 振り返り
#### 良かった点
- マシンの初期設定が去年3時間かかっていた所が30分で終わらせられた
- Goprofでスコアに影響が出にくいが改善できているかの可視化ができた
- BingChatを利用してエラーの解決の時間短縮ができた
- 1年間練習を継続できた
#### 来年に向けて
- Goの環境構築、ビルドの反映で時間がかかっていたのでローカルでビルド、アップロードを自動化出来るようにする
- ベンチを叩けない時間が長かったのでローカルで動作確認できるようにする
- Goの修正はbranchで確認、修正が確認できた後にマージする
- 3台編成の練習をする
- 仕様の理解を時間内にした上でスコアの改善に直結するような対策を取れるようになる

### 過去記事
https://qiita.com/akirago/items/eb42df918387fb7030ba
https://qiita.com/akirago/items/c3581551177887308a72
じゃんけん.py

# 乱数でじゃんけんに勝つ

#### 相手の傾向から次の勝利を予想する。

```python:main.py
import random
gu = 0
choki = 0
pa = 0
num = 0
gu_p = 1
choki_p = 1
pa_p = 1
up_p = 0.1
dict = ['gu','cho','pa']
while True :
    if num != 0:
        res = input("勝or負(w / l) ： ")
        if res == 'w' or res == 'l':
            pass
        else:
            res = random.choice(['w','l'])
        if gu == 1:
            gu = 0
            if res == 'w':
                gu_p += up_p
            else:
                if gu_p > up_p * 1.1:
                    gu_p -= up_p
                else:
                    pass
        elif choki == 1:
            choki = 0
            if res == 'w':
                choki_p += up_p
            else:
                if choki_p > up_p * 1.1:
                    choki_p -= up_p
                else:
                    pass
        elif pa == 1:
            pa = 0
            if res == 'w':
                pa_p += up_p
            else:
                if pa_p > up_p * 1.1:
                    pa_p -= up_p
                else:
                    pass
        else:
            pass
    w = [gu_p,choki_p,pa_p]
    val = random.choices(dict, k = 1, weights = w)
    val = val[0]
    if val == 'gu':
        gu += 1
        print('グー')
    elif val == 'cho':
        choki += 1
        print('チョキ')
    elif val == 'pa':
        pa += 1
        print('パー')
    else:
        pass
    #print([gu_p,choki_p,pa_p])
    num += 1
```
[FlutterFlow] 画面の向きを固定する方法

## はじめに
### FlutterFlowについて
[FlutterFlow](https://flutterflow.io/)は、爆速モバイルアプリ開発を実現する、画期的なビジュアルプログラミングツールです。簡単なアプリなら本当にその日のうちにテストフライトまでが完了していると優れたツールです。
### FlutterFlowの優れている点
FlutterFlowの優れた点として拡張性があります。プリセットで用意されていない機能や要素は自分でコーディングすることができるため、痒いところになるべく手が届くようになっています。

## 目標
アプリの画面を縦に固定するCustom Actionを作成して、アプリの全ページを縦画面に固定します。

## CustomActionの作成
サイドバーから、「Connect > CustomCode」を選択します。
新しい「CustomAction」を作成します。名前を`setPortraitUp`としてください。
Action Codeには以下のように記述します。
作成すると自動的に`import`が複数書かれます。この部分はその他の設定によって若干変わったりするので、以下の部分をコピペしてください。
```dart
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!
// この下の部分をコピペする

import 'package:flutter/services.dart';

Future setPortraitUp() async {
  // Use to set portraitUp
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
}
```
完了すると、右上のSaveActionで保存します。
完成例を載せておきます。

```dart:Custom Action
// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/actions/index.dart'; // Imports other custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom action code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'package:flutter/services.dart';

Future setPortraitUp() async {
  // Use to set portraitUp
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
}
```

![CustomActionの編集](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628974/e14e941a-0927-f60c-2df5-8925f8722f55.png)


## main.dartで呼び出す
先ほどの画面の「Custom Files」に`main.dart`が含まれています。これをクリックしてください。
右サイドバーから「File Settings」を選択します。
先ほど作成した`setPortraitUp`が選択肢にあるので、これを追加します。
こちらもSaveして完了。

![main.dartの編集](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628974/736856b0-35de-82b8-90b5-fbbe4bff5aa1.png)

## さいごに
これで完了です。
FlutterFlowのテスト画面では上手く動作しませんが、端末ではちゃんと動作するので、試してみてください。
このように、CustomActionを使用すると、FlutterFlowが提供している以外の機能も実現できますので、色々試してみてください。