OmniAICreator/Qiita-1.07M huggingface dataset:
【Next.js】Telemetryを無効にする方法

## はじめに

Next.js は、一般的な使用法に関する匿名のテレメトリデータを収集しています。
これを無効にする方法について記載します。

## 設定方法
無効にする方法は以下の2つあります。

- コマンドで無効にする
- 環境変数で無効にする

### コマンドで無効にする
以下のコマンドで無効にできます。

```zsh:ターミナル
npx next telemetry disable
```
または
```zsh:ターミナル
yarn next telemetry disable
```

無効になっているか確認します。

```zsh:ターミナル
$ npx next telemetry status
Next.js Telemetry

Status: Disabled

You have opted-out of Next.js' anonymous telemetry program.
No data will be collected from your machine.
Learn more: https://nextjs.org/telemetry
```

または

```zsh:ターミナル
$ yarn next telemetry status
Next.js Telemetry

Status: Disabled

You have opted-out of Next.js' anonymous telemetry program.
No data will be collected from your machine.
Learn more: https://nextjs.org/telemetry
```

## 環境変数で無効にする
環境変数で無効にするには`.env`に以下を追記します。
```.env
NEXT_TELEMETRY_DISABLED=1
```
discord.pyのエラー

pythonのdiscord.pyのアップデートをした際になるバグの直し方について
-------------------------------------------------------------
先日 ウイルスにかかってしまい pcのデータをバックアップした後に初期化したのですが
初期化後 pythonを再インストール+discord.pyなどのモジュールを入れ 起動しようとした際にエラーが出ました
そのエラーがこれです
![unknown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840859/2ce86cb0-68e4-f6c4-1a4e-c6db41678b84.png)
色々調べたのですが直し方が出なく困っていましたがいろいろ試行錯誤していたら治りましたので 直し方を解説します

step1
--
windowsの設定からpythonをアンインストール
(もしかしたらpythonのバージョンは関係ないかもしれません)

step2
--
python 3.10の最新版をダウンロード
python 3.10のインストール

step3
--
コマンドプロンプトで
pip install discord.py==1.7.0

あとがき
--

基本的にこれで動くようになるはずです
自分はpythonを再インストールしたのですが もしかしたら
pip uninstall discord.py
の後にstep3をやったらいけるかもしれません
治らなかったらすいません
【PHP基礎復習13】計算式

［問題］
ユキさんがいつも利用しているバスの運賃は、初乗り運賃が160円で、その後1区間ごとに40円足されていきます。
ｍ区間乗ったとすると、運賃はいくらになるでしょうか。



# コード
```PHP
 $input = fgets(STDIN);
 echo 160 + 40*$input, PHP_EOL;
```

↓　4と入力

# 結果
```
320
```
therubyracer と libv8 と libv8-node


## これはなに

Rails で開発されているプロダクトで [libv8] が使われており違いや浅く歴史について調べたので簡単にまとめました

## TL;DR

- [therubyracer] と [libv8] と [libv8-node] すべて JavaScript Engine V8 を実行バイナリである
- 最初は [therubyracer] が開発されていたが、 実行環境の差分追従などが困難になり [libv8] の開発を開始、その後再び困難になったことから [libv8-node] の開発が行われている
- [therubyracer], [libv8], [libv8-node] の何れかの利用が求められたら、現在は `libv8-node` を使うことが望ましい

## therubyracer について

[therubyracer] は JavaScript Engine V8 実行を行う binary を提供している Gem です

https://github.com/rubyjs/therubyracer

https://rubygems.org/gems/therubyracer

2018 年を最後に更新されておらず、 未対応の Platform 対応を希望する Issue も何度か作成されていますが、
後述する [libv8] や [libv8-node] に更新することを推奨されています

[therubyracer] には過去苦しめられた思い出も沢山ありますが今回は割愛するとともに、
[therubyracer] については以下記事やタグを参照してみてください

https://qiita.com/jkr_2255/items/1d4cf636e044c0093091

https://qiita.com/tags/therubyracer

## [libv8] について

[libv8] は [therubyracer] 同様に JavaScript Engine V8 実行を行う binary を提供している Gem です

https://github.com/rubyjs/libv8

https://rubygems.org/gems/libv8

README にも記載されているとおり、 [libv8] は [therubyracer] で V8 Engine の upgrade 追従が困難になったタイミングでスピンオフされたものです
[libv8] は [mini_racer] 等多くの Gem に利用されています

> **About**
> This project spun off of therubyracer which depends on having a specific version of V8 to compile and run against. However, actually delivering that version reliably to all the different platforms proved to be a challenge to say the least.
> We got tired of waiting 5 minutes for V8 to compile every time we installed that gem.

Node.js の v14 系までの実行は [libv8] を利用することが多かった印象です
こちらも 2020 年を最後に更新されておらず、 未対応の Platform 対応を希望する Issue も何度か作成されていますが、
後述する [libv8-node] に更新することを推奨されています

## [libv8-node] について

[libv8-node] は [libv8] や [therubyracer] 同様に JavaScript Engine V8 実行を行う binary を提供している Gem です

https://github.com/rubyjs/libv8-node

https://rubygems.org/gems/libv8-node

README にも記載されているとおり、 [libv8-node] は [libv8] の時と同様に V8 Engine の upgrade 追従が困難になったタイミングでスピンオフされたものです

> **About**
> This project spun off of libv8, which itself spun off of therubyracer which depends on having a specific version of V8 to compile and run against. However, actually delivering that version reliably to all the different platforms proved to be a challenge to say the least.

Node.js の v16 系と同等の実行環境を求められる場合は [libv8-node] を利用しましょう
現在サポートしている Platform も x86_64 系の CPU arch だけでなく arm 系も対応されています

## 結局何を使えば良いか

- [libv8-node] を使いましょう
- [libv8] や [therubyracer] を使っている場合は頑張って upgraede しましょう

## Reference

https://v8.dev

https://github.com/rubyjs

http://github.com/rubyjs/therubyracer

https://github.com/rubyjs/libv8

https://github.com/rubyjs/libv8-node

https://github.com/rubyjs/mini_racer

https://rubygems.org/gems/therubyracer

https://rubygems.org/gems/libv8

https://rubygems.org/gems/libv8-node

https://rubygems.org/gems/mini_racer

[therubyracer]: https://rubygems.org/gems/therubyracer
[libv8]: https://rubygems.org/gems/libv8
[libv8-node]: https://rubygems.org/gems/libv8-node
[mini_racer]: https://rubygems.org/gems/mini_racer
条件分岐 の書き方

# 目的
- 条件分岐と三項演算子の使い方を学ぶ。

# ポイント
- nil, false 以外は 真の値 となる。
- 三項演算子 は別のプログラミング言語でも使える。
- case文 は同じ変数を何度も使う際に使うとスッキリした条件分岐が書ける。



# 書き方の例
```ruby

#条件分岐
is_sunny = true
if is_sunny
  puts "晴れです。"
else
  puts "雨です。"
end

#三項演算子
is_sunny = true
is_sunny? (puts "晴れです。"):(puts "雨です。")

#case文
score = 30
case score
  when 20
    puts "no"
  when 30
    puts "yes"
end
```
~実際の表示〜
-  => 晴れです。

-  => 晴れです。

-  => yes

# 注意するポイント
- end が必要となる。

# 具体的な例
以下のコードを三項演算子にする

~サンプルコード~
```ruby
age = 22

if age >= 20
  result = "成人です"
else
  result = "未成年です"
end

puts result

#三項演算子
age = 22
age >= 20? (puts "成人です"):(puts "未成年です")


```
~プレビュー画面~
- => 成人です
- => 成人です
ROSA クラスターネットワーク情報

# はじめに
Red Hat OpenShift Service on AWS（ROSA）のデフォルト構成はどうなってるんだっけ、ということで確認したときの結果を書いておきます。今回はネットワーク構成について。
PodやServiceのIPの範囲の確認です。


# ROSAクラスター構成
以下のクラスター構成での情報です。
・[STSモード](https://docs.openshift.com/rosa/rosa_getting_started/rosa-sts-getting-started-workflow.html)
・[AWS PrivateLink cluster](https://docs.openshift.com/rosa/rosa_install_access_delete_clusters/rosa-aws-privatelink-creating-cluster.html)
・マルチゾーン

バージョン情報
```
$ oc version
Client Version: 4.10.4
Server Version: 4.10.20
Kubernetes Version: v1.23.5+3afdacb
```

# クラスターネットワーク構成確認結果

コマンドでの確認結果は以下の通りです。

```
$ oc get network.config/cluster -o yaml
apiVersion: config.openshift.io/v1
kind: Network
metadata:
  creationTimestamp: "2022-07-12T06:47:58Z"
  generation: 2
  name: cluster
  resourceVersion: "3067"
  uid: 241fa832-535d-4740-92e4-260d0422b696
spec:
  clusterNetwork:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  externalIP:
    policy: {}
  networkType: OpenShiftSDN
  serviceNetwork:
  - 172.30.0.0/16
status:
  clusterNetwork:
  - cidr: 10.128.0.0/14
    hostPrefix: 23
  clusterNetworkMTU: 8951
  networkType: OpenShiftSDN
  serviceNetwork:
  - 172.30.0.0/16

```

ということで、Cluster Network、Service Network以下の通り。
`Cluster Network：10.128.0.0/14`
`Service Networl：172.30.0.0/16`
`HostPrefix：23`　→512ノードまでOKとなるが、実際には[180](https://docs.openshift.com/rosa/rosa_architecture/rosa_policy_service_definition/rosa-service-definition.html#rosa-sdpolicy-compute_rosa-service-definition)が最大

# 参考
せっかくなので、公式マニュアルも確認しておく。
[CIDR range definitions](https://docs.openshift.com/rosa/networking/cidr-range-definitions.html) こちらを見ると、Service、Pod、Hostの他Machine CIDRも確認できる。
ROSAクラスター外のリソースとCIDRを分ける場合は、インストール時に各CIDRブロックを変更することもできる（[参考](https://docs.openshift.com/rosa/rosa_install_access_delete_clusters/rosa-sts-creating-a-cluster-with-customizations.html)）。
【Git】あとからSwift用の.gitignoreを追加する

# はじめに
この記事はほぼ自分用ですがいちおう公開にしておきます笑
もっとスマートな方法があったらコメントください

# やりかた
ローカルの`.DS_Store`を全て消す
```:ターミナル
find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch
```

`.gitignore`を作成
```:ターミナル
touch .gitignore
```

`.gitignore`を開く
```:ターミナル
open .gitignore
```

`.gitignore`に除外するパスを追加
```.gitignore
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## User settings
xcuserdata/

## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout

## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3

## Obj-C/Swift specific
*.hmap

## App packaging
*.ipa
*.dSYM.zip
*.dSYM

## Playgrounds
timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm

.build/

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build/

# Accio dependency management
Dependencies/
.accio/

# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output

# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/

UserInterfaceState.xcuserstate

.DS_Store

BuildTools/.build
BuildTools/.swiftpm
BuildTools/Package.resolved

*.swp

xcschememanagement.plist
```

コミットして反映
```:ターミナル
git add .gitignore
git commit -m 'add: .gitignore'
git push origin main
```

# 参考記事
https://it-engineer.hateblo.jp/entry/2018/12/21/091741
devise実装手順

## 毎回devise導入時コマンド忘れるので書き残しておく。
 以下のコマンドは一貫して行う。

```ruby:Gemfile
gem 'devise'
bundle
``` 
```ruby:ターミナル
$ rails generate devise:install
$ rails generate devise user  //　モデル

その後、何かカラムを追加してから
$ rails db:migrate 
$ rails generate devise:views
```
Formオブジェクトのedit定義

例えばitemsテーブルとtagsテーブルの2つを合わせたFormオブジェクトがあったとしたら、それを編集するためのeditアクションは下記のようになる。

```items_controller.rb
def edit
    @item = Item.find(params[:id])
    @tag = @item.tag
    item_attributes = @item.attributes
    tag_attributes = @tag.attributes
    item_tag = item_attributes.merge(tag_attributes)
    @item_tag = item_tag.new(item_tag)
end
```
attributesメソッドでそれぞれの値をハッシュとして取り出し、それらをmergeメソッドでハッシュを結合することで、編集したいitem_tagの情報を取り出すことができる。
HSTSプリロード とは

## 勉強前イメージ

HSTSとはまた違う？

## 調査

### そもそも HSTS とは

詳細は [こちら](https://qiita.com/miyuki_samitani/items/6869c1c202883a83f1ce) をご覧ください。

HTTP Strict Transport Security の略で、webブラウザに対してhttpsでの通信を強制するものになります。
webサーバとブラウザでの最初の通信の際に応答のところで
ヘッダ内に Strict-Transport-Security という項目を定義することで次回からの通信はhttpsで行うというものになります。

### HSTSプリロード とは

そしてHSTSプリロードとは初回アクセス時からhttps接続させるようにブラウザに通知する仕組みです。
HSTSプリロードで登録されているサイトはブラウザが自動的に最初からhttps通信を行うようになります。
注意点としては、サイト内の一部に非SSL化の頁があるとユーザはアクセスできなくなります。

また、 `HSTSプリロードリスト` というものがあります。
プリロードリストとはgoogleによってまとめられて主要ブラウザで使用されている、HSTS対応のサイトをリスト化したものになります。
[こちら](https://hstspreload.org/) から登録することができます。
ブラウザはプリロードリストを見て登録されている場合は最初からhttpsで通信を行うようになります。

### HSTSプリロードの確認項目

- SSL証明書が有効かどうか

SSL証明書があっても有効ではなかったり、期限が切れてたするとだめなので
有効かどうか確認が必要です。

- 同一ホストでhttp→httpsへリダイレクトしているか

301リダイレクトの設定を行うことが必要です。

- 常時SSL化が行われているかどうか

HSTSプリロードはドメイン一部に対しての対応ができず、ドメイン全体の対応が必要です。
例えば、 example.com というドメインがありその配下に `www.example.com` と `official.example.com` と `recruit.example.com` というサブドメインのサイトがあったとします。
HSTSプリロードは3つのサブドメイン・サブディレクトリも含めてすべてに対応するのですべてのページをSSL化対応する必要があります。

## 勉強後イメージ

確かに最初は鍵の交換とかで安全じゃないから、最初から安全にしましょう ってことか。
サブドメインがそんなないのであればいいかもしれないけど、万が一更新し忘れとかあったら怖いから登録は慎重にしないとね。

## 参考

- [3分で出来るHSTSプリロードの設定方法 - 常時SSL化後に必ず行うべき設定](https://labcoat.jp/hsts-preload/)
【Python】標準出力の出力先をファイルにする。

# はじめに
僕はiOSのPythonista3というAppで、よく寝っ転がりながらPythonするのですが、モジュールのヘルプを見ても英語がわからないのでGoogle翻訳が欠かせません。
一度、調べたこともすぐに忘れてしまうので、原文と翻訳テキストを保存しておくことにしました。

モジュールをインポートして`help(モジュール)`と入力し、コンソールに出力されるテキストを「すべて選択」し、エディタに張り付けるという作業なのですが、文字数が大きいと選択に時間がかかり、時にはAppが落ちてしまいます。

僕は寝っ転がりながら「コンソールに出力されるテキストを直接ファイルに書き込めたらいいのになぁ。」と普通に思いました。

# 結論から

~~~python:Python3
import sys

STDOUT = sys.stdout

sys.stdout = open('./tmp.txt', 'w')

help(sys)
 
sys.stdout = STDOUT
~~~
pythonの標準出力の出力先は`sys.stdout`になっていて、これを書き換えることで出力先を変更できるそうです。
1. まずは、もとに戻れるように`sys.stdout` を `STDOUT` にとっておきます。
2. 出力先をファイルに変えます。
3. 出力します。
4. `sys.stdout`をもとに戻します。


# `__stdout__`では戻らない
まずは、多くの方が紹介している方法を試してみました。
`sys.__stdout__`でもとに戻す方法は、ファイルには出力されるのですが、コンソール出力にに戻らなくなってしまいました。

```python:Python3
import sys

sys.stdout = open('./tmp.txt', 'w')

print("Hello")

sys.stdout = sys.__stdout__

print("World!")
```
```:tmp.txt
Hello
```
```:console
```
これが、メモに残そうとっしたきっかけなのですが、多くの記事で`sys.__stdout__`に戻すだけと紹介されていましたが、僕の環境ではうまく戻すことができませんでした。


ファイルには出力されているのですが、コンソールには何も表示されません。
一瞬、あせりましたが、Appを再起動したらもとに戻ってたので、「あせって損した」と思いながらドキュメントを見ることにしました。

## Python 3.10.6 ドキュメント<br>sys --- システムパラメータと関数
`sys.__stdin__`<br>`sys.__stdout__`<br>`sys.__stderr__`
> それぞれ起動時の stdin, stderr, stdout の値を保存しています。終了処理時に利用されます。また、 sys.std* オブジェクトが(訳注:別のファイルライクオブジェクトに)リダイレクトされている場合でも、実際の標準ストリームへの出力に利用できます。<br>
また、標準ストリームが壊れたオブジェクトに置き換えられた場合に、動作する実際のファイルを復元するために利用することもできます。しかし、明示的に置き換え前のストリームを保存しておき、そのオブジェクトを復元る事を推奨します。<br>
>>注釈 一部の条件下では、stdin, stdout, stderr も、オリジナルの __stdin__, __stdout__, __stderr__ も None になることがあります。これはコンソールに接続しない Windows GUI アプリケーションであり、かつ pythonw で起動された Python アプリケーションが該当します。

# つまり
寝っ転がるのをやめて、**win10のコマンドプロンプト**で試したら、`sys.__stdout__`で戻りました。
ついでに、**PyhtonIDLE**で試したら戻りませんでした。

つまり、「環境によって`sys.__stdout__`は使えない場合があるよ。」と理解しました。




# 参考にさせていただきました。
[sys --- システムパラメータと関数 — Python 3.10.6 ドキュメント](https://docs.python.org/ja/3/library/sys.html)
OBS ver.28からver.27に下げる方法

# はじめに

OBS　バージョン28がリリースされて色々と便利な機能が追加されたが、プラグインが未対応だったりバグってたりと問題があるみたい。
なのでひとまずバージョン27に下げる方法の紹介をする。

※僕の環境では設定も引き継がれて27に落とせたが何か問題が発生する可能性があるのでやるのは自己責任で

# まずはバージョンの確認

次の画像のように ヘルプ➔OBS Studioについて をクリックすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292551/550e99c9-ef01-4d24-cab5-4382e333daf3.png)

次のようなウィンドウがでてきてバージョンを確認できる。
この画像の場合は27.2.4(64bit)のところ。※カッコ内の数字(64bit or 32bit)は後ほど必要になるので覚えておく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292551/86cd2931-620f-15be-7cc8-b2ff0b337b56.png)

# 27に下げる方法

Google検索で[OBSのダウンロードページ](https://obsproject.com/ja/download)を探してアクセスする。

すると次のようなページがでてくるので以前のリリースをクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292551/1e24a320-a9da-6c8b-d9fe-e44adbcce9e1.png)

すると次のような英語たっぷりのページがでてくるので

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292551/9af40972-63eb-a4f9-432b-85a3c57472c1.png)

OBS Studio27.2.4のところまでスクロールしてこの文字をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292551/e901edde-3495-a4be-ab01-fb260f939b1c.png)

クリックした先で一番したまでスクロールすると次のようなAsettsがでてくる。

Windowsの64bitを使っている場合は `OBS-Studio-27.2.4-Full-Installer-x64.exe` を32bitを使っている場合は `OBS-Studio-27.2.4-Full-Installer-x86.exe` をクリックする。(ここで先程覚えておいたバージョンカッコ内の数字を使う)

するとインストールファイルがダウンロードされるので、そのファイルを開く。あとは指示に従っていけばバージョン27のOBSがインストールされる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292551/9ede75f3-ed5e-60b0-d430-a7b721666042.png)
【Node.js】MySQLのIN句に配列の要素を指定する方法

配列の要素をMySQLのクエリのIN句に指定したい時。
```
const selectUsers = [ '田中', '鈴木', '木下' ];

const sql = 'SELECT * FROM users WHERE name IN (?)';
const res = await mysql.query(sql, [selectUsers]);
```

参考：
https://qiita.com/komatsu_1324/items/df1253fb3d4b3e312d17
【閉じタグ忘れ・不要タグの検出】HTMLエラーチェッカー【Chrome拡張機能】

## HTMLエラーチェッカー

https://chrome.google.com/webstore/detail/html%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%81%E3%82%A7%E3%83%83%E3%82%AB%E3%83%BC/ohdllebchmmponnofchalfkegpjojcaf?hl=ja

Google Chromeの拡張機能です。
「閉じタグがない」「開始タグがない」エラーを教えてくれます。

タグの閉じ忘れや不要タグの残骸対策に役立ちます。

## 使い方

デフォルトではOFF
アイコンをクリックするとチェックしてくれます。

オプションの「`自動チェックを有効にする`」を「`ON`」にするとページを開くたびに自動でチェックをしてくれます。

## 参考ページ

https://hsmt-web.com/blog/html-error-checker/
Google Colaboratoryでmecab-ipadic-NEologdを使う方法

## Google Colaboratoryでmecab-ipadic-NEologdを使いたいがエラー出る場合

いろいろ記事はあるのですが、`Permission denied`に触れられているのがなかったので、書いておきます。

あと、Google Driveで作成したディレクトリ名にスペースが含まれているとうまくいかないので気をつけてください。

```sh
!apt-get -q -y install sudo file mecab libmecab-dev mecab-ipadic-utf8 git curl python-mecab
!git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
!chmod 755 -R mecab-ipadic-neologd
!echo yes | mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n
!pip install mecab-python3
!ln -s /etc/mecabrc /usr/local/etc/mecabrc
```

## チェック用コード

```py
import MeCab

m = MeCab.Tagger()
sample_txt = "彼女はペンパイナッポーアッポーペンと恋ダンスを踊った。"
print("Mecab:\n", m.parse(sample_txt))

path = "-d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd"
m = MeCab.Tagger(path)
print("Mecab ipadic NEologd:\n",m.parse(sample_txt))
```

## 参考

https://qiita.com/jun40vn/items/78e33e29dce3d50c2df1
Keil StudioとLPC812MAXで遊ぶ(Lチカ)


Keil StudioとLPC812MAXで遊ぶ(Lチカ)



目的
mbedオンラインコンパイラーが終了予定なので

青いろLEDが点滅


![o_con730.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/73f56d0c-67de-9c4a-3b26-c7a42ae2b153.jpeg)


![o_con731.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/551bcb14-33dc-deb1-48ed-f00625f22477.jpeg)



![o_con732.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/2501fd7c-24cb-fa8a-3bb3-86e678dfc21a.jpeg)



mbed2-example-blinky_821_1




```c++


#include "mbed.h"

DigitalOut myled(LED1);

int main() {
  while(1) {
    myled = 1;
    wait(0.2);
    myled = 0;
    wait(0.2);
  }
}


```



![o_con833.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/796c3d11-4d93-a4a8-1bcc-767b219c1c2b.jpeg)


-16-
【コードレビュー】 一見同じ値に見える引数の定義

業務上のコードレビューで気になったものの中から「一見同じ値に見える引数の定義」（ニホンゴムズカシ〜）についてまとめてみようと思います。

# 前提

指摘があったケースは関数内で次のような項目の登録処理をしていました。

- 書類に記載する日付
- 書類の送信日時
- 書類の登録日時

そして書類データはこの関数を呼出した時点で作成されます。

レビューの最初の時点で関数内では呼び出された日時をこれら3つの項目に登録するようにしていました。
```TypeScript
export const create = async (key: DataKey) => {
  const documentData = {
    key,
    date: new Date(),
    submittedAt: new Date(),
    registeredAt: new Date(),
  };
  return await save(documentData);
};
```

ですが、テストケースなどを考えるとこれらの項目はオプション引数として指定できる方がいいという指摘がありました。

# NG

実際の動きとしてはどれも現在日時を使っていたので、オプション引数としてデフォルトで現在日時を取るような引数を定義してしまいました。

```TypeScript
export const create = async (key: DataKey, options?: { documentDate?: Date }) => {
  const documentDate = options?.documentDate ?? new Date(); // 何も指定しない場合は現在日時
  const document = {
    key,
    date: documentDate,
    submittedAt: documentDate,
    registeredAt: documentDate,
  };
  return await save(document);
};
```

レビュイーは3つの項目が現在日時を登録するものだという考えで引数名を`documentDate`にしました。
ただ、それぞれ別の値を指定するようにこの関数を呼び出したい場合この定義だと対応できません。

# OK

3つの項目は目的が違うので、それぞれ指定できるようにしました。
指定されていない場合は現在日時をデフォルト値として使うようにしています。
関数を呼び出す側の仕様変更にも対応できるし、テストケースで色々な値を試したい場合も対応できます。

```TypeScript
export const create = async (
  key: DataKey,
  options?: {
    documentDate?: {
      date?: Date;
      submittedAt?: Date;
      registeredAt?: Date;
    };
  },
}) => {
  const defaultDocumentDate = new Date(); // 何も指定しない場合は現在日時をデフォルト値として使う
  const documentDate = options?.documentDate;
  const document = {
    key,
    date: documentDate?.date ?? defaultDocumentDate,
    submittedAt: documentDate?.submittedAt ?? defaultDocumentDate,
    registeredAt: documentDate?.registeredAt ?? defaultDocumentDate,
  };
  return await save(document);
};
```

# まとめ

今回は同一の書類データに登録するということで、分ける意味ある？となるかもしれませんが、別の種類のデータのための値の場合は明確に分ける必要があると思います。
1つの値を変更したら芋づる式にあちこちの値に影響するようなコードはデグレの可能性が高くなるので避けるようにしたいですね。
deviseの遷移先の指定はどうするか

## application_controller.rbへ記述する
```
def after_sign_in_path_for(resource)
  user_path  //　ユーザー詳細画面に遷移
end

def after_sign_up_path_for(resource)
  user_path  // ユーザー詳細画面に遷移
end

def after_sign_out_path_for(resource)
  new_user_session_path  // ログイン画面に遷移
end
```

application_controller.rbに上記のような記述をするだけで、deviseで新規登録した後の遷移先、ログインした後の遷移先、ログアウトした後の遷移先を指定できる。
Wi-Fi Alliance

# Wi-Fi Allianceとは

Wi-Fi Allianceとは、APを提供しているベンダーと顧客のスマホの間の接続を保証する規格を作る組織です。例えば、この組織がないと、ここにあるAPとは接続できたけど、このAPとは接続できないぞってなってしまいます。

# Wi-Fi Allianceのいろんなセキュリティ規格

| Wi-Fi Allianceのセキュリティ規格 | ユーザー認証方法 | 暗号化方法 |
| --- | --- | --- |
| WPA-Personal | 事前共有鍵 | RC4-TKIP |
| WPA-Enterprise | 802.1x/EAP, RADIUS Server | RC4-TKIP |
| WPA2-Personal, WPA-PSK | 事前共有鍵 | AES-CCMP |
| WPA2-Enterprise | 802.1x/EAP, RADIUS Server | AES-CCMP |

# ユーザー認証方法の説明

- 事前共有鍵とは、APがユーザーにパスワードをうかがって認証を行います。よく私たちの家にあるタイプですね
- 802.1x/EAPとRADIUS Server。802.1x/EAPはユーザーからAPにデータを飛ばすときに使うプロトコルです。そしてAPはRADIUSプロトコルを使ってRADIUSサーバーにデータを飛ばします。
Magic: The Gatheringはチューリング完全？典拠はどこですか？

# この記事について
Magic: the gathering(以下、Magic)というカードゲームはチューリング完全と言われているので、その根拠となる論文と軽い説明を書きます。

日本語の情報がとても少ないので...

(チューリングマシンを実際にどうシミュレーションすろのか、という点は論文をまだ読み終えていないので記述できません。)
# 関係図と解説

下の図は、Magicのゲームがどのようにチューリングマシンをシミュレートできるかを示した関係図です。

ここで、
- 「A ← B」は、「任意のAがシミュレーションできるBを構築することができる」
- 「A <...B」は、「あるAと等価なBを構築することができる」  

を意味します。ただし、この2つにチューリング完全性に関する特別な違いは無いと思われます。

```mermaid
graph BT

MtG -->| Chuchill など|UTM218 --> |Rogozhin| 2TS -.-> |Cockeなど|2TM -.-> |Shannon|TM

TM(チューリングマシン)
2TM(2記号のチューリングマシン)
2TS(2-タグシステム)
UTM218(2状態18記号の チューリングマシン)
MtG(Magic のゲーム)
```

- Shannonさんは、あるチューリングマシンと全く等価な2記号のチューリングマシンを作れることを示しました。[^2TM]
- Cockeさんらは、2記号のチューリングマシンを上手く変化させることで、それと等価な2-タグシステムが作れることを示しました。[^2Tag]
- Rogozhinさんは、任意の2-タグシステムをシミュレートする、プログラムがどのタグシステムでも同じなチューリングマシンの作成法を示しました。[^UTM218]
- Churchillさんらは、そのチューリングマシンのプログラムを、他のクリーチャーが死亡した際に誘発する能力を持ったクリーチャーで表現し、そのマシンをシミュレートするMagicのゲームが存在することを示しました。[^Mtg]

したがって、あるチューリングマシンと等価な2-タグシステムをシミュレートできる Magic のゲームはチューリング完全です。という論法でした。

--------
最後に、Magic 上でチューリングマシン(2状態18記号の)を動かしている動画を紹介します。

https://www.youtube.com/watch?v=pdmODVYPDLA

[^2TM]: SHANNON, Claude E. A universal Turing machine with two internal states. Automata studies, 1956, 34: 157-165.
[^2Tag]: COCKE, John; MINSKY, Marvin. Universality of tag systems with P= 2. Journal of the ACM (JACM), 1964, 11.1: 15-20.
[^UTM218]: ROGOZHIN, Yurii. Small universal Turing machines. Theoretical Computer Science, 1996, 168.2: 215-240.
[^Mtg]: CHURCHILL, Alex; BIDERMAN, Stella; HERRICK, Austin. Magic: The gathering is Turing complete. arXiv preprint arXiv:1904.09828, 2019.
【 Azure App Service 】PM2 コマンドを用いてアプリケーションを起動する方法

Azure Web App に React アプリケーションをデプロイした際、Web App デフォルトページが表示され、デプロイしたはず (つもりになっている) Web アプリケーションが反映されないという事象に遭遇 (2回目)。忘れた頃に、毎回 Azure Web App のスタートアップコマンドってどうやって設定するんだっけ？という状態に陥るので、手順をまとめておきたいと思います。(備忘録)

Azure App Service は MCR (Microsoft Container Registry) からコンテナイメージを pull して、コンテナ上でアプリケーションコードを実行できる PaaS です。一般的な Node.js ファイルが検出された場合は、自動的にプロセスマネージャーの PM2 (Azure Web App Node.js コンテナ付属) を使用して、アプリケーションを起動します。但し、Azure Web App ランタイムの ``Node 14 LTS`` を使用している場合には、コンテナは PM2 でアプリケーションを自動的に起動する処理は行われないようです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/10a51e1e-e8f1-de6d-04f4-7c9fbac60144.png" width="400">

そこで設定が必要になるのが、スタートアップコマンドです。Azure Web App のスタートアップコマンドは、コンテナウォームアップの一環として実行されます。スタートアップコマンドは、Azure Portal 上から設定することが可能です。

対象の Azure Web App リソースへアクセスして、ナビゲーションメニューから **設定 > 構成 > 全般設定** タブを開きます。

スタートアップコマンドの項目があるので、コマンドを入力します。

```
pm2 start <.js-file-or-PM2-file> --no-daemon
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/88fd8812-4df2-3f42-ee7a-de2100d4a403.png)

詳しい内容は公式ドキュメントをご確認ください。

[PM2 で実行する | App Service](https://docs.microsoft.com/ja-jp/azure/app-service/configure-language-nodejs?pivots=platform-linux#run-with-pm2)
TwitterAPIを使ってツイートを取得したりツイートを投稿したりする【Python + tweepy】

# やりたいこと
自動で何か喋ってくれるTwitterのbotを作りたい。
前回の記事。

https://qiita.com/fujii_273/items/bed7bf7b34fa0bb515c9

前回までで、僕のツイートを学習して文章を自動生成するところまでは出来ました。
今回は自動生成した文章をツイートするところまでやりたいと思います。
また、自動で僕のツイートを取得してDBに格納する機能もつけます。

# 開発環境
・Windows 10
・Python 3.10.7
・tweepy 4.10.1

# やったこと
１．tweepyのインストール
２．TwitterのAPI KEYの取得
３．ツイートを取得する機能の作成
４．ツイートから生成した文章をツイートする機能の作成

## １．tweepyのインストール

まず、PythonからTwitterAPIを実行するためのライブラリをインストールします。
今回は[tweepy](https://docs.tweepy.org/en/stable/install.html)というものを使います。

## ２．TwitterのAPI KEYの取得
botとして運用するアカウントを新規に作成して、Twitter開発者登録する。
するとAPI KEYが発行されるのでそれをメモする。
開発者登録の仕方は以下のページを参考にしました。

https://di-acc2.com/system/rpa/9688/

## ３．ツイートを取得してDBに格納する機能の作成
ざっくり書くとこんな感じです。
```TwitterAccessor.py
import tweepy

client = tweepy.Client(consumer_key    = ここにApi Key,
                       consumer_secret = ここにApi Key Secret,
                       bearer_token    = ここにBearer Token,
                       access_token    = ここにAccess Token,
                       access_token_secret = ここにAccess Token Secret,)

def getTweets():
	tweets = client.search_recent_tweets(query='from:ここにユーザ名 -RT', tweet_fields=['id', 'text', 'created_at'])
	return tweets.data
```

ポイントは``tweet_fields``引数でしょうか。
ここに欲しいツイートのフィールドを指定しています。
ツイートのID、本文、それと投稿日時です。

### ３－１．ツイートの投稿日時を日本時間に変換する
取得したツイートの日時がどうやら9時間ずれているようでした。
```
2022-09-08 03:56:52+00:00
```
なので、タイムゾーンを考慮した時間に変換します。
```Functiuons.py
def convertTime(timeStr, format='%Y-%m-%d %H:%M:%S%z'):
	postedOn = datetime.datetime.strptime(str(timeStr), format)
	return postedOn.astimezone().strftime('%Y-%m-%d %H:%M')
```
``strptime``関数で文字列からdatetime型にして``astimezone``で端末のタイムゾーンを適用した日時にします。

## ４．ツイートから生成した文章をツイートする機能の作成
取得したツイートをDBに格納したり、DBのデータを学習して文章を生成したりといった機能も用意しましたが、ここでは割愛させていただきます。
（そこの記事はまた別の機会に）

ツイートを投稿する処理はざっくりこんな感じ。
```TwitterAccessor.py
import tweepy

client = tweepy.Client(consumer_key    = ここにApi Key,
                       consumer_secret = ここにApi Key Secret,
                       bearer_token    = ここにBearer Token,
                       access_token    = ここにAccess Token,
                       access_token_secret = ここにAccess Token Secret,)

def postTweet(message):
	client.create_tweet(text=message)
```

``create_tweet``関数の``text``引数に文字列を渡しています。
最初、引数名を指定せずに直接``create_tweet(message)``としていましたが、エラーが発生したので引数名を明示しました。

この``postTweet``を実行すればツイートが投稿されます。

# 参考資料
https://docs.tweepy.org/en/stable/client.html?highlight=search_recent_tweets#tweepy.Client.search_recent_tweets

https://qiita.com/takaki@github/items/b1a380a0a644170f5885

https://di-acc2.com/tag/twitter-automation/
【 #ゆめみからの挑戦状 ★第5弾】をやってみた

お題はこちら
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【 <a href="https://twitter.com/hashtag/%E3%82%86%E3%82%81%E3%81%BF%E3%81%8B%E3%82%89%E3%81%AE%E6%8C%91%E6%88%A6%E7%8A%B6?src=hash&amp;ref_src=twsrc%5Etfw">#ゆめみからの挑戦状</a> ★第5弾】<br>シリーズ初の PHP 問題です😎✨<br><br>【お題】<br>以下のぐちゃぐちゃな配列を期待されている形に整形して出力してください<br><br>【回答方法】<a href="https://t.co/rZguz6aKJX">https://t.co/rZguz6aKJX</a> またはソースコードのスクリーンショットを引用 RT<br><br>【結果発表】<br>9/15（木）<br><br>【出題者】<br>まっぴー <a href="https://twitter.com/mpyw?ref_src=twsrc%5Etfw">@mpyw</a> <a href="https://t.co/GSpE5Tekmp">pic.twitter.com/GSpE5Tekmp</a></p>&mdash; 株式会社ゆめみ | YUMEMI (@yumemiinc) <a href="https://twitter.com/yumemiinc/status/1567724142811820033?ref_src=twsrc%5Etfw">September 8, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

ksort にオプション付けられるの知らんかった^^;
<blockquote class="twitter-tweet"><p lang="zxx" dir="ltr"><a href="https://t.co/vOh902fJgk">https://t.co/vOh902fJgk</a><a href="https://t.co/CTDjJGhtV9">https://t.co/CTDjJGhtV9</a> <a href="https://t.co/KLaRkC132n">pic.twitter.com/KLaRkC132n</a></p>&mdash; ロングもみあげガール推進部 (@kb10uy) <a href="https://twitter.com/kb10uy/status/1567748813531795457?ref_src=twsrc%5Etfw">September 8, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

パクったら4行 → 3行になった！

```php
<?php
$in = [
    ['2nd' => 'two', 'four' => '4th'],
    'three' => '3rd',
    ['one' => '1st'],
    '10th' => 'ten',
    ['6th' => 'six'],
    '5th' => 'five',
    'seven' => '7th',
    ['fourteen' => '14th', '11th' => 'eleven'],
    ['8th' => 'eight'],
    'thirteen' => '13th',
    '12th' => 'twelve',
    'nine' => '9th',
    ['15th' => 'fifteen'],
];

$ans = [
    '1st' => 'one',
    '2nd' => 'two',
    '3rd' => 'three',
    '4th' => 'four',
    '5th' => 'five',
    '6th' => 'six',
    '7th' => 'seven',
    '8th' => 'eight',
    '9th' => 'nine',
    '10th' => 'ten',
    '11th' => 'eleven',
    '12th' => 'twelve',
    '13th' => 'thirteen',
    '14th' => 'fourteen',
    '15th' => 'fifteen',
];

preg_match_all('/"(\d{1,2}..)":"([^"]+?)"|"([^"]+?)":"(\d{1,2}..)"/', json_encode($in), $m);
$list = array_merge(array_combine(array_filter($m[1]), array_filter($m[2])), array_combine(array_filter($m[4]), array_filter($m[3])));
ksort($list, SORT_NUMERIC );
var_export($list === $ans);//true
```
4行が最小じゃね？って事だったんで多分最小ｗ
gh コマンド（GitHub CLI）で GLIBC が見つからないエラーを解決する（Ubuntu）

## 環境

- Ubuntu v20.04.5
- WSL2
- Homebrew v3.6.0
- GitHub CLI (gh) v2.15.0（brew でインストール）

## 問題の事象

```console
$ gh
gh: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by gh)
gh: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by gh)
```

## 解決法

```sh
brew uninstall gh
brew install gh
```

## 最後に

原因を解明したわけではないので記事にするほどでもないのですが、もしかすると同様の事象で困っている方がいるかも知れないので一応記録を残しておきます。
スクラムチェックリスト

### プランニングチェックリスト
```
・プランニング前に、おおよそPBIのサイズ基準でスプリントに選択できるPBIが充分にあること

・プランニングでタスク切りをする（4hが最大）

・プランニングでPOと今スプリント何をやるかを約束できていること（限定的なやれたらやるなどは許容）

・メンバーの今後の稼働時間の考慮がされているか

・各PBIにDODは記載されているか
```
### リファインメントチェックリスト：
```
・PBIの最大サイズが決められており、超過しないようにPBIを分割できているか
・次のスプリントで実施するPBIのみで終わっていないか
・完了時に1スプリント分以上の見積もり済みPBIがあること
・見積もり済みPBIはDODが記載されているか
・[※必須ではないができているとさらに良いこと]貯金として次スプリントでやるものだけでなく、1ヶ月分の貯金ができていること)
```

### レビューチェックリスト：
```
・ステークホルダーとチームは対話できない雰囲気でないか
・ステークホルダーの意見を元にPBIの組み替え、内容変更ができる、いずれできる環境か
・完了ステータスのものだけレビューされているか
・POがレビューの場で初めて成果物を確認するようなことになっていないか
・レビュー対象のPBIに関係のあるステークホルダーが参加できる場合、参加しているか
```

### レトロチェックリスト：
```
・レトロで予定時間と実績時間のグラフもしくは図があるか
・消化SPの推移のグラフはあるか（グラフ作成は新卒の方にやっていただく案もある）
・レトロによって有用な改善点は最低一つでも生まれているか、それが具体的か
・チームが振り返り、改善をするために必要な指標やグラフが足りているか
・プランニング時のcommitmentが破られている場合は原因解明と改善を行う必要があり、その場合議論が行われているか
・今スプリント、割り込みタスクがあったか、それがどれくらいかかったかの報告があったか（なかったという報告で終わっても良い）
・DODの変更、追加によってコミットメントに悪影響があった場合、それが議論されたか（なかったという報告で終わっても良い）
```
### デイリーチェックリスト：
```
・進捗がちゃんと共有されているか
（例えば、今日やること、明日やること、困っていることを共有するなど）
```
### イベント全般：
```
・タイムボックスがちゃんと守られているか
・参加者が適切に参加しているか
（デイリーにステークホルダーが参加して発言しているようなことがないか）
・スプリント途中でdevとPOの両方の許可なくdodが変更されていないか
```

### スクラムマスター：
```
・スクラムガイドを毎スプリント少しづつでも読み進めて理解を進めていること（最長2ヶ月以内に理解をする）
・POの不満や疑問を少しでもヒアリングする機会を作っているか（SMでもdevでも）
・[必須ではないができているとさらに良いこと]長期的な開発のための知識として、例えば技術的負債についての対策のためエクストリームプログラミングなど、スクラムガイド以外の知識習得をしているか　
```
802.11h/e/i/k/v/rの特徴について

# 802.11hのDFCとTPCについて

802.11hは以下の二つの機能を持っています。

## DFS

- DFSとは、Dynamic Frequency Selectionの略で、そのままの意味で、動的に周波数を変える機能のことです
- レーダーや衛生システムがU-NII-2またはU-NII-2Eの領域を使うので、無線通信の機器が同じ領域のチャネルを使う場合は、DFSを組み込んで干渉を起こさないようにする必要があります。

## TPC

- TPCとは、Transmit Power Controlの略で、動的に機器の電力レベルを調整する機能のことです。
- 二つの装置が通信しているとその通信にかかる電力のレベルが最小限になるようにします。電力が弱まることで発生する電波も弱まり、他の通信機器と干渉しづらくなります。

# 802.11eの無線通信の質向上について

- 遅延がとても大きくなるとデータが損失してしまうので、音声、動画などはネットワーク通信においてとても繊細な情報です。
- そこで、802.11eは、アプリケーションに優先順位を設けることで、無線通信の質を向上させます。

# 802.11iのセキュリティについて

- 802.11iはインターネット接続にパスワードをもうけました。いつも私たちがインターネットにアクセスするときにパスワードを要求されますよね？まさにそれです
- こうすることで、権限のない人はインターネットを利用できません。
- しかも、これはAESアルゴリズムを利用したCCMPという暗号化技術で通信データを暗号化しているので安心です。
- ちなみにユーザーネームとパスワードはRADIUSサーバーで管理しています。

# 802.11kについて

チャネルのリストを作ることで近くの利用可能なAP検索を高速化するのに役立ちます。例えば、あなたは部屋を移動すると接続していたAPの電波が弱まりますよね？そのときにあなたのスマホは接続ができる近くのAPを探します。

# 802.11vについて

APの接続切り替えをスムーズにする規格です。例えば、あなたは、どこかに移動したいとします。すると、802.11vの規格によって移動先のAPの混雑状況がわかります。こうすることであなたはネットワーク通信が良好な場所に移動することができます。

# 802.11rについて

これは他のAPに接続を切り返した際の認証をスムーズにします。事前共有鍵(PSK)と802.1xの両方で機能します。
【CraftCMS】MatrixフィールドでSuperTableを使う時の注意点

# 経緯
matrixのブロックで定義したSuperTableフィールドの画像フィールドのパスの定義として

```
/data/img/記事セクション/記事ID/
```

としたかったのでアセットアロケーションは

```twig
[データパス] img/{owner.section.handle}/{owner.id}
```

と設定したのだが記事登録してみるとこんなエラー


> The Entry Image field’s Upload Location setting has an invalid subpath (“{owner.section.handle}”).

どこにアップすんねんエラーです。

# ownerとは誰なのか

matrixフィールドに於けるownerとは、**そのフィールドが紐付けられたエントリ** を指してます。

SuperTable in matrixの場合

```
Entry 
　┗ Matrix
 　　┗ SuperTable
```

こういうことになりますので〜

Entryのsectionを拾いたい場合は

```twig
[データパス] img/{owner.owner.section.handle}/{owner.owner.id}
```

SuperTableから見た所有者(Matrix)の所有者、つまりEntryということになるっぽいです。

owner.idはエラーにならなかったけど、これはmatrixフィールドのIDを取得していたからなので
地味に設定ミスだったということが判明しました。

**おわり。**
[Laravel]日付のダミーデータで期間を指定する

# はじめに
日付のダミーデータをいれる際に、期間を指定してランダムな日にちを生成する方法がわからなかったので、備忘録として残しておきます。

# 環境
- Laravel：8.83.4

# 1. 実装



```php
//略
    public function definition()
    {
        return [
            'date' => $this->faker->dateTimeBetween($startDate = 'now', $endDate = '+4 week'),
        ];
    }
//略
```
上記のコードで、今日から4週間後までの期間を指定しています。
また、今回は利用しませんでしたが、
`($startDate = '-3 week', $endDate = '+2 week')` のように指定することで、今日より前の期間でデータを生成することも可能です。

日付の指定だけでなく、数値範囲を指定する`numberBetween()`のようなメソッドもあるので、うまく活用していきたいです。

# 2. 参考文献

https://fwhy.github.io/faker-docs/formatters/date_time/date_time_between.html
127.Promiseチェーン

#promiseなしとありで比較しながら書いてみよう
#### promiseなし
```js:promiseなし
function sleep(callback, val) {
  setTimeout(function() {
    console.log(val++);
    callback(val);
  }, 1000);
}

sleep(function(val) {
  sleep(function(val) {
    sleep(function(val) {
      sleep(function(val) {
  
      }, val);
    }, val);
  }, val);
}, 0);
```
#### promiseあり
```js:promiseあり
function sleep(val) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      console.log(val++);
      resolve(val);
    }, 1000);
  });
}

sleep(0).then(function(val) {
  return sleep(val);
}).then(function(val) {
  return sleep(val);
}).then(function(val) {
  return sleep(val);
}).then(function(val) {
  return sleep(val);
}).then(function(val) {
  return sleep(val);
})
```
#### <大まかな流れ>
1.関数を実行する
2.Promiseが生成
3.setTimeout内での処理を行う
4.then以下に1を再び実行する処理を行う
#### <もう少し細かくみると>
1.sleep(0).を実行
2.return new Promiseとして、Promiseが生成される。　
3.resolveを引数にして、Promise(関数)をいれる
4.setTimeoutを記述し、第一引数にresolve(val)を実行
5.実行するとthen以下のsleep(val)が返えるので再び1に戻る

#### キーポイント
＊非同期処理を続けるには,Promiseを生成し続けなければならない
→そのためPromiseを返却し、常に静止しなければならない
ゆめみの採用試験の模試をPythonで解いてみた

Qiitaの存在を知らせてくれた企業、株式会社ゆめみ。
コードチェックのレベルが高いと評されて、私も自分の力が足りなかったので落ちました。
落ちた後、残念さに公式ホームページの[エンジニア応募者向けの模試](https://www.yumemi.co.jp/serverside_recruit)をPythonで解いてみました。
ちなみに、この試験で完全に自信を失ってしまったので、6ヶ月後の再受験はあきらめるつもりです:frowning2:
(日本語は未熟なので、文法が違ったり、ぎこちなければ教えてください！)
# 考え方
- 複雑なアルゴリズムを使うのは面倒だからPASS
- 手軽に読みやすく作成しよう

requirements.txtを編集することで外部ライブラリ使用が可能でしたので、pandasを使用しました。

# 問題

このようなCSVから以下の条件で抽出する。
```
create_timestamp,player_id,score
2021/01/01 12:00,player0001,12345
2021/01/02 13:00,player0002,10000
2021/01/03 12:00,player0021,100
2021/01/04 12:10,player0031,200
2021/01/05 12:00,player0041,300
```
- プレイヤー平均点の上位10人を抽出する。
- スコアは四捨五入し、同点の場合は11人以上抽出される場合がある。
- プレイヤー数は1万人以下、ログは数千万行。
# 入出力例
```
$ ./get_ranking game_score_log.csv
rank,player_id,mean_score
1,player0001,10000
1,player0002,10000
3,player0003,9000
4,player0004,7000
5,player0005,1000
6,player0006,999
7,player0007,998
8,player0008,997
9,player0009,990
9,player0010,990
9,player0011,990
9,player0012,990
```
# 出力ルール
- 各プレイヤーにおける、全てのプレイの平均点を利用した上位10名を出力
- 出力は3列のCSV形式とする
- 1行目はヘッダとして、rank,player_id,mean_scoreを出力する
- 上記ヘッダに準じて2列目以降を出力する
- rankの項目には平均スコア上位から1,2,3,…の数字が割り当てられる
- 平均スコアは四捨五入で整数で丸められる
- 同点の平均スコアのプレイヤーが居た場合、rankingの数字は同じ数字が割り当てられる
- 同点の平均スコアのプレイヤーが居た場合において、10名以上のランキングが作られる事がある
# 回答

```Python
import pandas as pd
import sys

# 引数をもらう部分です。Trackで実行するために必要です。
args = sys.argv[1:]
command_line_argument = args[0]

# 受けた引数を通じて当該ファイルを読む作業を行います。
data = pd.read_csv(str(command_line_argument), encoding='utf-8')

# 四捨五入とソーティングの処理
data = data.groupby(['player_id'], as_index=False).mean()
data.score = data.score.round()
data['rank'] = data['score'].rank(method='min', ascending=False)
data = data.sort_values(by='rank')

# 出力のルールを合わせるためにColumnの名前とタイプを変更
dataNew = data[['rank', 'player_id', 'score']]
dataNew = dataNew.rename(columns={'score': 'mean_score'})
dataNew['rank'] = dataNew['rank'].astype(int)
dataNew['mean_score'] = dataNew['mean_score'].astype(int)

# 上位10名をカットして出力します。
dataNew = dataNew.nlargest(n=10, columns='mean_score', keep='all')

# print(data)、CSVとして保存
dataNew.to_csv('result.csv', index=False)
f = open("result.csv","rt")
c = f.read()
print(c)
```
![re.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822440/82f539bc-de2e-cf21-9794-be01f006b6a1.jpeg)

- 09/09 追加
コードチェックでも出力を私の勝手にして落ちたので恥ずかしいです。
間違った部分があれば知らせてください:sweat_smile:

# 感想
普段よく使うpandasを利用したデータ処理を利用すれば簡単に解くことができました。
Atcoderも企業のコードテストも、日本のテストは難しいですね…。
勉強します！:books:
ハニーポットをOCIにデプロイする


ハニーポットをOCIでちょっと試してみたい方向けに[T-Pot](https://github.com/telekom-security/tpotce)のデプロイの手順を紹介します。意図的にセキュリティレベルを低下させることになるため、自己責任で注意してご使用下さい
T-PotはDebian11で動作するため、今回はDebian11のVMインスタンスを用意し、T-PotをPost Installする方法で行います

## Debain11のVMインスタンスの作成
- Debianの公式サイトからDebian11の[Cloudイメージ](https://cloud.debian.org/images/cloud/bullseye/20230124-1270/debian-11-genericcloud-amd64-20230124-1270.qcow2)をダウンロード
- オブジェクトストレージにDebian11のCloudイメージをコピー
- カスタムイメージにDebian11のCloudイメージをインポート
- カスタムイメージからDebain11のインスタンスを作成する
    - パブリックサブネットを指定、転送中暗号化の使用のチェックを外す

## T-Potのインストール
```
UserIDはdebian, インスタンス作成時の秘密鍵でログイン
$ sudo apt-get update
$ sudo apt-get install git

#SSHをパスワード認証に変更
$ sudo vi /etc/ssh/sshd_config
PasswordAuthentication no -> yesに変更
$ sudo systemctl restart sshd
$ sudo passwd debian

#T-Potのインストール
$ git clone https://github.com/telekom-security/tpotce
$ cd tpotce/iso/installer/
$ sudo ./install.sh --type=user

```

- STANDARDを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/15a827f6-7eb1-b91a-c697-d4cc2802c8a7.png)

- ユーザー名とパスワードを指定(コンソールアクセスで使用)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/d7587f97-41aa-b027-21e0-3e2df4a607f1.png)

インストール完了後、自動的に再起動される

## インストール後の設定

T-Potの管理に必要なポート64294,64295,64297をVNCのセキュリティリストのイングレスルールでオープンする
[T-Potの動作に必要なポート](https://github.com/telekom-security/tpotce#required-ports)(実際に攻撃を受けるポート)をオープンする。個別のポート指定が面倒な場合はALLで

T-PotのVMインスタンスにSSH接続するには、ポート22でなく64295を使用する
T-Potの分析用コンソールは、https://VMのパブリックIP:64297

- プリセットされているkibanaの分析ダッシュボード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/48cb1e8b-82a5-5801-a413-697b9872e953.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/e9eff52e-e943-f8b5-082e-f97c4f998e91.png)

T-Potが監視している攻撃の種類やそれぞれのダッシュボードが分析している内容などは、公式のGitや有識者のサイトなどから情報収集してみると良いでしょう。ツール自体は古くからあるので、いろんな情報にヒットすると思います
ノンデザイナーズ・デザインブック を読んでみた

[ノンデザイナーズ・デザインブック](https://www.amazon.co.jp/dp/4839955557) をデザイナーにお勧めされたので読んでみました．

ソースを書くときにも意外に意識していそうなものがあったので，
自分なりの理解を含めて軽く紹介します．

## ノンデザイナーズ・デザインブック

デザインの「4つの基本原則」について説明されています．
ロングセラーらしいので，いい本なんだと思います．

- 近接
- 整列
- 反復
- コントラスト

## 近接

意味の近いものをグルーピングします．

ソースコードでは，関数化するまででもないものでも，一区切りのものに対して空行を入れて対応したりします．

## 整列

すべてが意図を持って配置されなければならない．

一貫性のあるフォーマッタが近い感じがします．
インデント以外にも書き方が揃うことで，同じ意味であることを強調できると思います．

## 反復

全体を通した一貫性を保つこと．

一貫性なので，整列で書いてしまったのですが，あえて言えば，同じものを同じように書くこと．でしょうか．

インデントなどが共通化されるのは良いのですが，
意識して同じものを同じように書かなければ本当の一貫性を保つことができないことがあります．

例えば，関数定義や変数定義の順番などです．
lint ツールで保証したりすることもあるでしょう．

## コントラスト

違うものを違うとわかるようにする．

逆に同じものを同じように書くこととも言えるかもしれません．
共通化した残りの部分が，強調されていると考えても良いかもしれません．

ソースコードだと，エディタによる色付けも近いかもしれません．

## まとめ

最初に読もうと思ったときに想定していたのと違う発見がありました．
何かの参考になれば幸いです．
GA4の移行についてのお悩みメモ

UAで運用しているサイトのGA4移行に取り組んでいる中で、UAとGA4の違いに苦労した（している）ことを紹介します。個人的見解が多分に含まれているので、ご承知おきください。

# GA4とは

ユニバーサルアナリティクス（UA）の次世代バージョンにあたるGoogleアナリティクスです。

# どうして移行が必要なの？

2023 年 7 月 1 日以降、標準のユニバーサル アナリティクス プロパティでデータが処理されなくなります。

# GA4の移行作業

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189459/466f0cf5-440c-39a4-3d4d-467b4817c291.png)

何回かクリックするだけで既存のUAプロパティをGA4プロパティに接続することができる。
GA4プロパティ作成前のデータは転送されてこないため、早めに作成してUAとの違いを確認しておくと吉。

# GA4で何が変わるの？
## ダッシュボードが大幅に変わる
- どこになにがあるかわからない
- ダッシュボード自体（サイドメニュー等）のカスタマイズもできるよう

## 計測単位と計測方法が変わる
- 計測単位はページからイベントへ
- 計測方法はセッションからユーザへ


## ビューの概念が廃止
- ~~GA4からはプロパティ配下のビューがなくなり、代わりに「データストリーム」の追加が可能になりました。~~
- データストリームはビューの代替ではない


## データストリームが追加
- Web、アプリといった異なるプラットフォームを同じプロパティで管理する

![7402B460-72AB-4200-BE74-20F4B03C1489.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189459/3ac6200d-c832-3a75-7f63-61835aa58c00.jpeg)


## レポート機能が基本レポートと探索レポートに分かれた
- 基本レポート
    - 既存の「ホーム」で確認できていた内容に近い
    - 表示するパネルをカスタマイズすることができる
- 探索レポート
    - 既存の「カスタムレポート」に近い（のかな…？）
    - セグメントを分けたり、色々な形式で詳しい分析が行える
    - 作成したレポートは共同編集が出来ず、他ユーザは閲覧と複製のみができる


## サブプロパティ（GA4 360）
- これが既存のビューに近い代物なはず。
- 参照元のプロパティから特定のイベントを抽出or除外したプロパティを作ることができる
- サブプロパティで収集したイベントの50%が課金対象

![FEA6A20A-438B-4129-A805-81862E7F2BE2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189459/fa138201-1653-5f0a-9ef6-1ce87f906cb4.jpeg)



## 統合プロパティ（GA4 360）
- サブプロパティの逆
- 複数の参照元プロパティのデータを統合して1つのプロパティで確認ができる
- 統合プロパティで収集したイベントの50%が課金対象
javascriptのObject.entriesについて

# Object.entriesとは
オブジェクトを配列に変換するメソッド
基本文法は以下の通りです。

```javascript:javascript
Object.entries(obj)
```

上記の文法を利用すると、オブジェクトが配列に変わるらしいので、実際にやっています。

# オブジェクトと配列に変換
```javascript:javascript
const obj = { "a": 1, "b": 2, "c": 3 }
const result = Object.entries(obj)
console.log(result) // [["a", 1], ["b", 2], ["c", 3]] 
```

上記のように`obj`のオブジェクトが配列に変わる。
keyとvalueが一つの配列になり、それらを含むすべての配列を返す。
これが、Object.entriesの大きい働きである。
jetpack composeでviewModelのデータを監視する

# 初めに
従来の`DataBinding`などの実装では、`ViewModel`に`LiveData`を持たせてそれを監視することで`view`の状態を切り替えていました。
しかし`jetpack compose`になってからは`MVVM`という設計自体が向いてないという話も出てきてはいますが、代替案がないのが現状です。
そこで今回は、`jetpack compose`を使った`ViewModel`のデータを監視する方法を紹介していきます。
### 本文
基本的には今まで`LiveData`を使ってた部分を`StateFlow`に変えればいいだけです。
そして、`Compose`に対して引数として該当画面の`ViewModel`を渡してあげれば、変数として監視することができます。
また、`Compose`側で値を変更したくないので`ViewModel`内で宣言する時は下記のようにするのがベストだと思います。
```kotlin
private val _hoge = MutableStateFlow("")
val hoge: StateFlow<String> get() = _hoge
```
# 最後に
今後アーキテクチャ自体が変わっていき、必要なくなる可能性もありますが現状においては割とベターな実装なのかなと思い、備忘録程度に書かせていただきました。
参考になったら嬉しいです
[Rails SQL] Cannot delete or update a parent row: a foreign key constraint fails の解決法

## 前提
progamesテーブルとchatroomsテーブルが１対１の関係。（progamesテーブルがchatroomsテーブルを持っている。）

## 発生しているエラー
SQL文のdeleteメソッドでpro_gamesテーブルのレコードを全て削除しようとすると以下のエラーが発生。
```
Cannot delete or update a parent row: a foreign key constraint fails
```

## 解決
先に親を消しているのが原因。子を先に消しておくとうまくいく。
（今回の場合だとchatroomsテーブルから消しておく。）
## なぜ親からだと削除できない？？
モデルに`dependent: :destroy`を書いているのになぜ削除できない？？
```ruby
class ProGame < ApplicationRecord
  has_one :chatroom, dependent: :destroy 
end
```
## 原因発覚
SQL文で削除しようとしたことが原因。
```ruby
resources :pro_games, only: [:create]
```
destroyメソッドはモデルを介するので、dependent: :destroyが効く。しかしdeleteメソッドはモデルを解さない。よってモデルに記載した`dependent: :destroy`が効かなかった。
## deleteメソッドとdestroyメソッドの違い
`delete`メソッド(または`delete_all`)はモデルを介さず直接SQL文をDBに送る。
`destroy`メソッド(`destroy_all`)はモデルを介してSQL文を送る。
delete、delete_all、destroy、destroy_allメソッドについてはこちらの記事([https://qiita.com/kamelo151515/items/0fa7fb15a1d2c1e44db2](https://qiita.com/kamelo151515/items/0fa7fb15a1d2c1e44db2))。
## まとめ
よって次から削除するときはdestoryメソッドでモデルを経由して削除するか、先に子を消すように意識する。
### 参考にした記事
[#1451 - Cannot delete or update a parent row: a foreign key constraint fails の解決法](https://inouelog.com/mysql-cannnot-delete/)
UiPath サービスモードでUnattendedをインストール＆セットアップ

Windowsログインしていない状態からインストール＆セットアップするときの手順の備忘録

1.msiからカスタム>Unattendedを選択

※Studioが欲しい場合はUnattendedをインストールした後でもう一度インストーラーをたたいて追加が必要

2.Orchestrator設定

2-1Adminからロボットアカウントを登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/75d54538-1974-537e-a14d-575261026ebc.png)

2-2そのままAdminでランタイムをテナントに対して登録する

ロボットユニットの数が必要！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/1aea02a2-a913-894b-4a4c-4baaaae82af4.png)

2-3 ｵｰｹｽﾄﾚｰﾀー>テナント>マシンを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/e1eedaaa-445f-4f25-a424-aa5697f80557.png)

2-4 ライセンスを割り当ててプロビジョニング
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/30b264c8-61ff-28ec-ef2b-b94874f111a6.png)

→これでマシンキーを発行できる！　作成したマシンの詳細に記載有
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/63ca1822-72f2-492c-4179-b301ef926e16.png)

2-5 Assistantで接続
マシンキーを入れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/03f67d4b-2f5d-1691-e426-f050737e8663.png)

URLは　http://からアカウント名 +　テナント名　の部分まで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/29a2efea-815e-1f30-3376-fe4fb2464f35.png)

2-6 フォルダーにユーザーを割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/5eb76e6b-cc2a-1536-3ea5-6a4e1ff39286.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2826228/0c5dcdd6-47b8-3ef3-acfb-6cbb00f1adf7.png)


自分の端末で設定する場合はWindowsログインIDをcmd & whoami で取得

VDIの場合は下記記事参照
https://qiita.com/SuetakeYoichi/items/d0628dfec34ebfe11ed3

やっとできました～！！！

終わり
javascriptのObject.assignとは

# Object.assignとは
オブジェクトを併合するメソッド。
まず使用方法は以下の通りです。

```javascript:javascript
Object.assign(target, ...sources)
```

# 特徴（働き）
Object.assignの最初の引数はターゲットです。
また、二番目からの引数はオブジェクトになります。
結論は、二番目からの引数（オブジェクト）は全て一番目の引数に併合される特徴を持っています。
では実際にコードで確認します。

#### 複数のオブジェクトを一つにまとめる

```javascript:javascript
const obj1 = {a: 1}
const obj2 = {b: 2}
const obj3 = {c: 3}

const newObj = Object.assign({}, obj1, obj2, obj3)
console.log(newObj) // { "a": 1, "b": 2, "c": 3 }
```
上記のコードのようにObject.assignは`obj1`,`obj2`,`obj3` のオブジェクトを簡単に一つにまとめることができます。
ただしここで注意すべき点があります。
```javascript:javascript
const obj1 = {a: 1}
const obj2 = {b: 2}
const obj3 = {c: 3}

const newObj = Object.assign(obj1, obj2, obj3)
console.log(newObj) // { "a": 1, "b": 2, "c": 3 }
console.log(obj1) // { "a": 1, "b": 2, "c": 3 }
```

一番目の引数にからのオブジェクトではなく、`obj1`を入れた場合、`obj1`に上書きされてしまいます。
こういう理由で、もし`obj1`の変更を望まない場合、Object.assignの一番目の引数にはからのオブジェクト入れる必要があります。
【jQuery】tableにアコーディオンを実装＆兄弟要素内の子要素を指定する

こんにちは。E-kan株式会社の岡田です。

先日、２０行以上あるtableタグで組まれているお客様の社内用データベース管理ページの改修を行ったのですが、地味に苦労したので備忘録。

#### やりたいこと
- デフォルトは最初の２行を見出しとして表示させ、残りの行はアコーディオンで折りたたむ
- tableの下に「詳細を表示する」というテキストを置き、クリックするとアコーディオンが開き、「詳細を閉じる」という文言に変える
- アコーディオンを閉じたら見出し行の位置に戻る
- テーブルは複数あるので、個別にアコーディオンが開くようにする

```html
<section class="accordion">
  <table>
    <thead>
      <tr>
        <th>タイトル１</th>
        <td>本文１本文１</td>
      </tr>
      <tr>
        <th>タイトル２</th>
        <td>本文２本文２</td>
      </tr>
    </thead>
    <tbody class="accordion_body">
      <tr>
        <th>タイトル３</th>
        <td>本文３本文３</td>
      </tr>
      〜〜〜　略　〜〜〜
      <tr>
        <th>タイトル２０</th>
        <td>本文２０本文２０</td>
      </tr>
    </tbody>
  </table>
  <span class="more">詳細を表示する</span>
</section>
```

## jQuery
```javascript
$(function(){
  //アコーディオン部分を非表示にしておく
  $('.accordion_body').hide();
  
  //.more をクリックしたら実行
  $('.more').on('click',function(){
    //クリックした要素の兄弟要素内の子要素（開閉させたい箇所）を変数に格納する
    var acBody = $(this).siblings(".accordion").children(".accordion_body")
    
    if(acBody.is(':hidden')){ //アコーディオンが非表示だったら実行する内容
      acBody.show(); //アコーディオンを表示させる
      $(this).addClass('active').text('詳細を非表示にする'); //テキストを変えてclassを付与
    } else { //アコーディオンが表示されていたら実行する内容
      acBody.hide(); //アコーディオンを非表示にする
      $(this).removeClass('active').text('詳細を表示する'); //テキストを戻してclassを取る
      var offset = $(this).parent().offset().top; //ページ上部から親要素の頭の位置までを変数に格納
      $(window).scrollTop(offset); //スクロール位置を見出し行に戻す
    }
  });
});
```

こんな感じの、クリックした直下の要素を開閉させる単純なアコーディオンなら
```html
<dl>
  <dt class="more">タイトル</dt>
  <dd class="accordion_body">本文</dd>
</dl>
```
nextとslideToggleを使ってサクッと実装出来るのですが、
```javascript
$('.more').click(function(){
  $(this).toggleClass('active');
  $(this).next('.accordion_body').slideToggle();
});
```
今回は既存のtable要素の一部をアコーディオンとして開閉させたいという事と、開閉のトリガーになる要素が兄弟要素ということで地味に苦労しました。（siblingsメソッドを初めて知った。勉強になった。）
あと、最初はアコーディオンをslideDown・slideUpにしていたのですが何故かアニメーションにならず、調べたところtableタグではアニメーションをサポートしていないとのことでした。

> 参考
> https://www.web-dev-qa-db-ja.com/ja/jquery/%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E8%A1%8C%E3%81%A7slidedown%EF%BC%88%E3%81%BE%E3%81%9F%E3%81%AFshow%EF%BC%89%E9%96%A2%E6%95%B0%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%EF%BC%9F/958218212/

まぁ、最近はtableを使うこともそんなに無いかと思いますが、アニメーションさせたいのなら最初からtableで組んじゃだめということですね。
Ineffective mark-compacts near heap limit Allocation failedエラーの解決

npm run buildしたところ

```terminal
Ineffective mark-compacts near heap limit Allocation failed
```

というエラーが。

その場合
```terminal
export NODE_OPTIONS="--max-old-space-size=4096
```

を打って領域を増やすと大丈夫でした。
※4096の部分は1024とか確保できるメモリ量によって変更必要です。