OmniAICreator/Qiita-1.07M huggingface dataset:
OctoberCMSでECサイトを作る (Shopaholic編２：製品の登録＆表示)

[前回](https://qiita.com/pikanji/items/c72eccc65d5f128a73d2)はShopaholicをcomposerでインストールする方法を説明した。
今回は製品を登録して、フロントエンドサイトで製品を表示するところまでを説明する。

## 製品を登録する
"Catalog" メニューから製品を登録することができる。
![shopaholic 2.jpg](https://qiita-image-store.s3.amazonaws.com/0/138322/6efc4a99-ac0b-1de1-800f-f87949b29e9e.jpeg)

`URL`はURL中でこの製品を特定するのに使用するユニークなキーを入れる。次のセクションで言及している`slug`がこれである。

次に"Offer"について。

Productsの登録画面には価格を登録するところがない。価格はOfferで管理されているためだ。

Offerとは同じ製品に条件次第で異なる価格設定を登録するためにある。
例えば、セットで購入する場合に値段を割安にする、ということが考えられる。

ということでOffersタブから価格を登録する。

## 製品を表示する
表示するには`ProductPage`コンポーネントまたは`ProductData`コンポーネントを使用する。
これらは、`ProductPage`が`slug`プロパティで製品を指定するのに対して、`ProductData`は`get()`メソッドにIDを渡して指定するだけの違いしかない（と思う。正直、２つある意味はよくわからない）。

どちらを使っても良いが、[ProductPageのドキュメント][ProductPage]から拝借したサンプルコード(を少し補完したもの)は下記のようになる。
[ProductPage]: https://github.com/lovata/oc-shopaholic-plugin/wiki/ProductPage

```twig
title = "Product"
url = "/product/:slug"
layout = "default"
is_hidden = 0

[ProductPage]
slug = "{{ :slug }}"
==

{# Get product item #}
{% set obProduct = ProductPage.get() %}
<div data-id="{{ obProduct.id }}">
    <h1>{{ obProduct.name }}</h1>
    {% if obProduct.preview_image is not empty %}
        <img src="{{ obProduct.preview_image.path }}" title="{{ obProduct.preview_image.title }}" alt="{{ obProduct.preview_image.description }}">
    {% endif %}
    <span>Category: {{ obProduct.category.name }}</span>
    <span>Brand: {{ obProduct.brand.name }}</span>
    <span>Brand: {{ obProduct.brand.name }}</span>
    {% set obOffer = obProduct.offer.first() %}
    {% if obOffer.isNotEmpty()%}  
        <span>Price: {{ obOffer.price }} {{ obOffer.currency }}</span>
    {% endif %}
    <div>{{ obProduct.description|raw }}</div>
</div>
```

次回はアイテムをカートに入れるとこまで。
[PyTorch] torch.repeat と torch.expand の違い

# torch.repeatとtorch.expandの違いを知りたい！
## 導入
例えば、
1階テンソル[0,0,0]を複製して
[[0,0,0], [0,0,0], [0,0,0]]みたいに2階テンソルにしたい時があると思います。

そんな時使うメソッドとして候補に上がるのがtorch.repeatとtorch.expandですが、これらはどう違うのか
気になったので実験しました。

## 実験

```
>>> import torch
>>> a = torch.zeros(3, 1)
>>> b = a.repeat(1, 4)
>>> c = a.expand(3, 4)   # a.expand(-1, 4)でも可能
>>> b.shape
torch.Size([3, 4])
>>> c.shape
torch.Size([3, 4])
>>> b
tensor([[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]])
>>> c
tensor([[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]])
>>> b[:, 2] += 1
>>> c[:, 2] += 1
>>> b
tensor([[ 0.,  0.,  1.,  0.],
        [ 0.,  0.,  1.,  0.],
        [ 0.,  0.,  1.,  0.]])
>>> c
tensor([[ 1.,  1.,  1.,  1.],
        [ 1.,  1.,  1.,  1.],
        [ 1.,  1.,  1.,  1.]])
```

要はこういうことでした。
元となるテンソルaをdataごと複製して新しいメモリに割り当てるのかどうかという違いでした。
てかdocumentationにもそう書いてあったわ

## 結論

複製したテンソルを個別にいじりたいならdataごと複製できるtorch.repeat
そうでないならメモリを節約できるtorch.expandを使おう

ということでした。

また注意としてtorch.expandは次元数が1の軸でないとexpandできないです。
torch.repeatは次元数が1より大きくてもrepeatできる
メモリの制約のせいかな
pandas で sqlite3 の読み書き

## sqlite3 データベースファイルの作成

```py:sqlite3_create.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	sqlite3_create.py
#
#					Oct/01/2018
# ------------------------------------------------------------------
import sys
import pandas as pd
#
import	sqlite3
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
df = pd.DataFrame([
		["t1271","千葉",51476,"2003-9-25"],
		["t1272","勝浦",42573,"2003-3-16"],
		["t1273","市原",28471,"2003-6-21"],
		["t1274","流山",36872,"2003-8-27"],
		["t1275","八千代",24176,"2003-11-5"],
		["t1276","我孫子",13275,"2003-1-12"],
		["t1277","鴨川",85194,"2003-12-18"]])

print(df)
#
file_sqlite3 = "./cities.db"
conn = sqlite3.connect(file_sqlite3)
#
#
df.to_sql('cities',conn,if_exists='append',index=None)
#
conn.close()
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

## sqlite3 の読み込み

```py:sqlite3_read.py
#! /usr/bin/python
#
#	sqlite3_read.py
#
#					Mar/05/2023
# ------------------------------------------------------------------
import sys
import pandas as pd
#
import sqlite3
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
file_sqlite3 = sys.argv[1]
conn = sqlite3.connect(file_sqlite3)
#
df=pd.read_sql_query('SELECT * FROM cities', conn)
print(df)
# print(df.head())
#
conn.close()
df.to_csv("tmp001.csv",header=None,index=None)
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行結果

```text
$ ./sqlite3_read.py cities.db
*** 開始 ***
       0    1      2           3
0  t1271   千葉  51476   2003-9-25
1  t1272   勝浦  42573   2003-3-16
2  t1273   市原  28471   2003-6-21
3  t1274   流山  36872   2003-8-27
4  t1275  八千代  24176   2003-11-5
5  t1276  我孫子  13275   2003-1-12
6  t1277   鴨川  85194  2003-12-18
*** 終了 ***
```

## 確認したバージョン

```text
$ python
Python 3.10.9 (main, Dec 19 2022, 17:35:49) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas
>>> pandas.__version__
'1.5.3'
```
Kotlin Androidでログ（Logcat）が出力されないときの対処法

<h3>概要</h3>
Androidスマートフォン向けアプリケーション開発にて、コード中に記載した `Log.d(TAG, props)` のようなログ出力が表示されないときの対処法を以下に示す。

<h3>検証環境</h3>

- Android Studio 3.1.4
- macOS Sierra バージョン10.12.6

<h3>原因</h3>

Logが出力されない原因は、　 `Log.d(TAG, props)` の `props` 変数が `null`　だから。

<h3>対策</h3>

`Log.d(TAG, "props: " + props)` の様に文字列連結して、 `Log.d()` の第二引数が `null` とならないようにしたら、 `props` が `null` のときもログ出力される。

【追記】
コメント欄にて、 @SorrowBlue さんにご指摘いただきました。

`Log.d("TAG", "$props")`

という具合に、変数展開すると、nullの時は"null"と出力されるようです。
文字列連結よりも便利ですね。👏

<h3>備考</h3>

業務で使うのなら、標準ライブラリである `android.util.Log` をラップしたclassをつくって、nullならnullと出力したり、envによって出力を出し分けたりなどするほうが親切でいいかも。
How to count NaN values by using isnull() and sum()

print(train.isnull().sum())
print(test.isnull().sum())


Output(below)
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64
PassengerId      0
Pclass           0
Name             0
Sex              0
Age             86
SibSp            0
Parch            0
Ticket           0
Fare             1
Cabin          327
Embarked         0
dtype: int64
ubuntu18.04にセカンダリIPを付与する

# 1.まえがき
ついにAWSでもUbuntu18.04がメインでリリースされましたが、ネットワークの設定ファイルがnetplanへ変更になって、セカンダリIPの設定がわからないよぉ!ドラ○も〜んとなったのでメモ書き

※[こちら](https://red-full-moon.com/secondary-ip-to-ubuntu-18-04-on-aws/)に画像つきの最新版を公開しましたので、よければ遊びに来てみてください。

# 2.ちゅういじこう
AWSコンソール上でのセカンダリIP付与の行い方は、先人達のありがたい記事がたくさんあるので割愛。
あと、実は[公式](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-ubuntu-secondary-network-interface/)に手順は書いてあるのですが、これをコピペするとインデントの問題で弾かれるので、そこを修正してます。
(むしろそこくらいしか修正していない)

# 3.ほんぺん

さて早速、新しいネットワークのyamlファイルを作るよ!

`$ sudo vi /etc/netplan/40-cloud-init.yaml`

```/etc/netplan/40-cloud-init.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    ens5: # NIC name
      addresses: [xxx.xxx.xxx.xxx/xx, yyy.yyy.yyy.yyy/yy]
      dhcp4: no
      routes:
        - to: 0.0.0.0/0
          via: zzz.zzz.zzz.zzz # Default gateway
          table: 1000
        - to: xxx.xxx.xxx.xxx
          via: 0.0.0.0
          scope: link
          table: 1000
        - to: yyy.yyy.yyy.yyy
          via: 0.0.0.0
          scope: link
          table: 1000
      routing-policy:
        - from: xxx.xxx.xxx.xxx
          table: 1000
        - from: yyy.yyy.yyy.yyy
          table: 1000
```

同ディレクトリに50-cloud-init.yamlというのがあるけど、それはそのまま
**消しちゃだめ**
また、先頭の番号で優先順位があるので、50より若くしておくことおおすすめ。
書き終わったら、更新するぞ。

`$ sudo netplan --debug apply`

でエラーログがでなければ完成
`$ ip a`
で確認してください。

```
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether hoge brd ff:ff:ff:ff:ff:ff
    inet xxx.xxx.xxx.xxx/xx brd hoge scope global dynamic ens5
       valid_lft 3549sec preferred_lft 3549sec
    inet yyy.yyy.yyy.yyy/yy brd hoge scope global secondary ens5
       valid_lft forever preferred_lft forever
    inet6 hoge scope link
       valid_lft forever preferred_lft forever
```

こんなふうにIPが2つ出たら成功。
一応wgetとかで外と疎通できるかも確認しよう。
(確認大事)

再起動後、ネットの疎通がしばらく遅くなりますが、辛抱強く待ちましょう!!

お疲れ様でした〜

ブログ始めました、よかったら遊びに来てください
https://red-full-moon.com/
application/x-www-form-urlencoded指定されているフォームにNode.jsでaxiosを使ってPOSTする方法

[公式ドキュメント](https://github.com/axios/axios#using-applicationx-www-form-urlencoded-format)

# 概要
自分が結構詰まったのでメモです。

# querystringを使う方法(Nodeのバージョンを問わない)
```javascript
const querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
```
こちらの方法がバージョンを問わず公式ドキュメントでも使われているのでおすすめです。
自作のライブラリでquerystringを使った実装があるので参考にどうぞ。
https://github.com/SugarShootingStar/nomlish/blob/master/src/main.js

# URLSearchParams()を使う方法(Nodeのバージョンが10以上)
```javascript
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
```
公式ドキュメントには記述されていませんが、nodeのバージョンが10以上の場合、URLSearchParams()がそのまま使えるようになっているのでquerystringをrequireしなくても動かすことができます。
しかし、自作ライブラリ等で複数バージョンに対応したい場合は上記のquerystringを使った方法のほうが無難です。

また、[Node8にも一応URLSearchParams()は用意されているのですが](https://nodejs.org/dist/latest-v8.x/docs/api/url.html#url_class_urlsearchparams)こちらを使う場合はこうなります。
しかし私がこの方法を試した所上手く動きませんでした。サイトとの兼ね合いかもしれませんが…

```javascript
const { URLSearchParams } = require('url');
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
```
Nuxt.jsのstyleブロックでlang="postcss"を有効にするとvscodeで適切にシンタックスハイライトされる

Nuxt 2(1でも？未確認)では `yarn add postcss-loader` すると何も設定しなくても `style` ブロックでpostcssを使うことができます。しかしながら、vscodeでVueのシンタックスハイライトをしてくれるVeturはそこまで考慮してシンタックスハイライトしてくれないのでpostcssのコードにエラーが出てしまいます。もちろん、nuxtは適切にコードを解釈できるのでvscode上のエラーさえ気にしなければ開発はできます。

(↓nuxtはエラーを出さないがvscode上ではエラーが表示される例)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/3387/44f57e3e-7fed-922d-80a2-d087221ef85c.png)

逆に`style`ブロックに`lang="postcss"`と指定してしまうとvscode上では適切な表示を得ることができますが、nuxtがwebpackに登録したローダーでは検知できなくなってしまうのでnuxtがエラーを吐きます。

そこで一つの解決策として`lang="postcss"`と指定したときに使用されるローダーを追加してしまうという手が考えられます。以下のように`nuxt.conifg.js`を編集することで`lang="css"`と指定したときと同じ出力結果を`lang="postcss"`でも得ることができます。

```js:nuxt.config.js

module.exports = {
...
  build: {
    extend(config, ctx) {
      for (let rule of config.module.rules) {
        if (rule.test.test('.css')) {
          config.module.rules.push({
            test: /\.postcss/,
            oneOf: rule.oneOf
          });
        }
      }

      return config;
    }
  },
}
```

この手法は一時しのぎにすぎず、本来であればVeturとnuxtが連携してcssに適用されるローダーを検知するようになっているべきです。ですので そう遠くないうちに こんなことをしなくてもよくなるかもしれません。
Barocco MD650L

リーズナブルな分割式メカニカルキーボードMiSTEL Baroccoにロープロファイルな新型MD650Lが出ました。日本ではまだ売ってないようですが入手方法や前機種との差異をまとめます。



手前: MD650L 奥:MD600
![unnamed.jpg](https://qiita-image-store.s3.amazonaws.com/0/16962/d4f65498-4551-0d8c-7a12-5c375fd87162.jpeg)

# 変更点
通り一遍のレビューは下記に詳しく出ているのでそちらを参照していただきたい。
エルミタージュ秋葉原: [超小型な分離キーボードの新境地。ロープロ仕様に生まれ変わった、MISTEL「MD650L」を試す](
http://www.gdm.or.jp/review/2018/0719/269597)

ここでは実際の使用感に基づいた私の個人的な見解を述べます。

- Cherry ML Low Profile key  
ストロークがMXの4mmからMLでは3mmに減少。これは快適だが赤軸に慣れていたので、茶軸のようなTactileのあるCherry MLはいまいち好きになれない。互換キーのKalihからはロープロファイルでもRed(Linear)/Brown(Tactile)/White(Clicky)の3種が出ているので、今後に期待。

- カーソルキー
無くてもいいんだけど、ちょっとしたwebゲームなんかをするのに便利。

- ケーブル
カールケーブルじゃなくなってとても良い

- キー設定
手順も含めて[前機種MD600](https://qiita.com/hakaicode/items/8569e58ce61385ff5fa5)とほぼ同じように設定できる。
レイアウト変更(QWERTY, Colemak,Dvorak)は<kbd><kbd>Fn</kbd>+<kbd>A</kbd></kbd>から<kbd><kbd>Fn</kbd>+<kbd>'</kbd></kbd>(シングルクォート)に変更になりました。気づかずに押してしまうとつらい。アーキサイトから[日本語マニュアル](http://www.archisite.co.jp/wp-content/uploads/2019/02/MD650L-web-manual.pdf)が公開されました。

- Dip SW
新しく追加されたけど使っていない
  1. <kbd>Caps</kbd> <kbd>Fn</kbd>置換
  2. <kbd>Caps</kbd> <kbd>R-Ctrl</kbd>置換
  3. <kbd>L-Meta</kbd> <kbd>L-Alt</kbd>置換　(Macでしか使わないならキーボードでできて嬉しいかも、でもMacで[karabiner](https://pqrs.org/osx/karabiner/)を使えば特定のキーボードプロファイルの時のみ変更してくれる機能があるので、MacBook内蔵キーボードと外付けキーボードでマッピングを変更することができます。Dip SWでは変更しない方がLinux/Windowsに繋いだ時にそのまま使えて良さそう。)
  4. L-SpaceをFnにして2つのFnキー

- Caps Switch LED
今までの3LEDの左側に白いCaps LockのLEDが付きました。

# 入手方法
[日本Amazon](https://amzn.to/2JLrTKH)から買えるようになりました。

[mechanicalkeyboards.com](https://mechanicalkeyboards.com/shop/index.php?l=product_detail&p=3519)から通販
- 送料等込で$198
- USからの郵送で到着時に謎のうんこ臭がしましたがすぐ消えました([セカイラボの人も言ってました](https://sekailab.com/wp/2018/08/31/review-mistel-barocco-md650l/))

米amazonでも扱っていますが日本への発送はできません。

# 雑感
- キーが静音赤軸ベースならなお良かったですが、お気に入りとしてメイン環境で使っています。
- FPSをプレイ中にWキーが壊れた！と思ってバラしてスイッチも開けたんですが、なにかの拍子にキーアサインが変わっただけでした。ツメが削れちゃったので次開けられないかも。壊れたと思う前にリセットの事を思い出してください。
- 最近は互換キーのKaihuaを採用してメカニカル+無線でも5000円くらいから買えるようになったので、この流れが分割式キーボードにも来てほしいですね。安物はバッテリがすぐ駄目になりそうな気はします。
<無線メカニカルキーボード>
  - [RK61](https://amzn.to/3byOBAn) ¥5,499-
  - [MOTOSPEED](https://amzn.to/3dBqN0B) ¥5,980-
- ErgoDox買ったんですが全く使わず押入れの肥やしになっています。もったいない。
- 深圳では青軸でLEDチカチカのキーボードばかりでした。中国や台湾の人はああいうの好きですね。ビジネスビルも夜中はLEDでレインボーしてます。
UnityでMVP行列を自前で渡す


```csharp

//各行列の取得方法

var viewMat = _camera.worldToCameraMatrix;
var projMat = _camera.projectionMatrix;
var modelMat = _gameObject.transform.localToWorldMatrix;

```

```glsl

//シェーダー側

float4 worldPos = mul(_ModelMat,v.vertex );
float4 viewPos = mul( _ViewMat, worldPos );
float4 projPos = mul( _ProjMat, viewPos );

```
細菌叢解析ツールの共有〜Dockerコンテナ〜

#はじめに
ひょんなことからとある大会でスライド発表してきました。
では、そちらをご紹介させていただきます。
※大会のスライドを少し省略しております。
※また、がちがちにキンチョーしていたので、こんなフランクには語っておりません。

---
![つるおか_ページ_05.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/ffebe478-325a-42da-ac8c-7f437aea1c9a.jpeg)
・[NCBI](https://www.ncbi.nlm.nih.gov/)などの公共データからダウンロードしたデータ。[vsearch](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5075697/)を利用して解析します。

---
![つるおか_ページ_07.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/9721795c-87a2-4a35-bc1b-86edec75f317.jpeg)
・解析ツールを構築するためには様々なソフト、パッケージが必要なんです。大変！

---
![つるおか_ページ_09.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/9d9e0a13-98b4-c384-9dce-9ef4b6394401.jpeg)
・出来た！動いた！　共同研究者よ、君にもどうぞ！
・・・あれ動かない。。。

---
![つるおか_ページ_10.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/d75a03b7-13a9-dd65-0b97-6c1aac7bb945.jpeg)
・[Docker様](https://www.docker.com/)の登場です。

---
![つるおか_ページ_12.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/9582b300-6069-67b7-3fe6-6f0663915760.jpeg)
・Dockerのいいところを並べてみました。

---
![つるおか_ページ_15.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/c6e5c5c6-7cd4-2347-8450-b0ef202b247d.jpeg)
・dockerイメージの説明です。いろんなイメージをダウンロードできるのです。おなじみの[ubuntu](https://hub.docker.com/_/ubuntu/)や[python](https://hub.docker.com/_/python/)などの公式イメージもありますよ。

---
![つるおか_ページ_18.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/7532f90f-5417-b7ec-6f82-a3d9f472f93f.jpeg)
・自分でも作れます！Dockerfileを作成し、ビルドするとDockerイメージになります。

---
![つるおか_ページ_21.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/4319359c-849a-9777-1c5c-11c38ae377be.jpeg)
・DockerfleはDockerhubにアップロードします。
・共同研究者や使用したい人がDockerイメージをダウンロードして各々で使用してもらえます！

---
![つるおか_ページ_22.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/228bbbf3-7d74-3987-d2ab-d594bebbb8dd.jpeg)
・はい、みんな幸せ！！

---
![つるおか_ページ_28.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/103821e5-c038-cbfc-d1a6-0e77f9653360.jpeg)
・気になる点&解決策をたらたら・・・（１）

---
![つるおか_ページ_29.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/69b52316-795f-ccda-2c6c-8223680ca0a1.jpeg)
・気になる点&解決策をたらたら・・・（２）

---
![つるおか_ページ_30.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/ee0b899c-d473-ba69-85b2-6484e10619fb.jpeg)
・[Galaxy](http://www.pitagora-galaxy.org/)
・[Google colaboratory](https://colab.research.google.com/notebooks/welcome.ipynb)
・[Rstudio.cloud](https://rstudio.cloud/)

---
![つるおか_ページ_32.jpg](https://qiita-image-store.s3.amazonaws.com/0/241094/da4ea818-594d-c353-4a49-c8aaa75b337a.jpeg)
以上です。ありがとうございました！

---
##参考URL
[効率的に安全な Dockerfile を作るには](https://qiita.com/pottava/items/452bf80e334bc1fee69a)

・過去の記事リンク
[RstudioCloudの使い方](https://qiita.com/petadimensionlab/items/ea164445e455d2c52b66)
[Docker for Mac 勉強メモ〜インストール〜](https://qiita.com/petadimensionlab/items/76bb169723e57bdc0133)
[Docker for Mac 勉強メモ〜コマンド集〜](https://qiita.com/petadimensionlab/items/328c546b06fd073fe409)
[超新人プログラマー(見習)がまず手にした本と参考にしたWEBサイト〜Docker編〜](https://qiita.com/petadimensionlab/items/4963adf9fb882c05fc5e)
俺のArchlinux

# 前置き
いつもインストールするとき忘れたりするのでメモ

64bit UEFI環境です.

# 準備
UEFIでセキュアブート,CSMを切る

# パーティション分け ＆ マウント
## インストールするドライブの確認
~~~
fdisk -l
~~~
今回は/dev/sdaにインストールするとする.

## UEFIで起動しているかの確認(あればOK)
~~~
ls /sys/firmware/efi
~~~

## パーティションを分ける
~~~
cgdisk /dev/sda
~~~
内訳はこんな感じで

|パーティション  |ラベル |サイズ  |タイプ  |
|---|---|---|---|
|/dev/sda1  |EFI  |512M |ef00  |
|/dev/sda2  |ROOT  |お好きに |8300 (デフォルト)  |
|/dev/sda3  |HOME  |お好きに |8300 (デフォルト)  |

## フォーマット
~~~
mkfs.vfat -F32 /dev/sda1
mkfs.ext4 /dev/sda2
mkfs.ext4 /dev/sda3
~~~

## マウント
~~~
mount /dev/sda2 /mnt
mkdir /mnt/boot
mkdir /mnt/boot/efi
mkdir /mnt/home
mount /dev/sda1 /mnt/boot/efi
mount /dev/sda3 /mnt/home
~~~

# インストール
## ミラー設定
tsukubaとjaistを上に持ってくる

~~~
vi /etc/pacman.d/mirrorlist
~~~

## インストール
~~~
pacstrap /mnt base base-devel
~~~

## fstab作成
~~~
genfstab -U /mnt >> /mnt/etc/fstab
~~~

# 設定
~~~
arch-chroot /mnt
~~~

## パスワード
~~~
passwd
~~~
## ホストネーム
~~~
echo HOSTNAME >> /etc/hostname
~~~

## ロケール
~~~
echo LANG="en_US.UTF-8" >> /etc/locale.conf
ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
locale-gen
~~~

## ユーザ追加
~~~
useradd -m -g wheel USER
passwd USER
~~~

## sudo
~~~
pacman -S sudo
visudo
~~~
以下2つのコメントアウト外す

~~~
Defaults env_keep += "HOME"
%wheel ALL=(ALL) ALL
~~~

## dhcp
有効に

~~~
systemctl enable dhcpcd
~~~

## とりあえず入れる
~~~
sudo pacman -S vim git
~~~

## GRUBインストール
~~~
pacman -S grub  dosfstools efibootmgr
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=arch_grub --recheck --debug
grub-mkconfig -o /boot/grub/grub.cfg
~~~

再起動～～～
npm publishする時の注意点

npm(nodejsのパッケージマネージャー)には簡単に自作のモジュールをuploadできます。

> [初めてのnpm パッケージ公開 \- Qiita](https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2)

こちらの記事で初回アップロードの手順は詳細に書いてあります。  
初回はもちろん、バージョンアップして２回目以降の`npm publish`をする時の注意点を記しておきます。

## 手順

- test
- READMEの確認
- TODOの確認
- ソースコードのbuild
- GitHubにpushしてCI(travis等)のtest
- npm versionの更新
- npm publish

## test

とにかくtest通ってなければ話になりません。`npm run test`

## READMEの確認

コードをガシガシ書いてテストが通ったら満足してしまいがちですが、公開するならREADMEに新機能の説明を追加するのを忘れてはいけません。

## TODOの確認

私は開発中に思いついた機能、メソッド名の変更、バグなどに気づいたらソースコードにTODOを埋め込むようにしています。

エディタにもよりますが、visualstudio-codeでは色んなTODO管理の拡張機能がありますのでそれを使います。

> [Search results \- todo \| Visual Studio Code , Visual Studio Marketplace](https://marketplace.visualstudio.com/search?term=todo&target=VSCode&category=All%20categories&sortBy=Relevance)

バージョンアップ公開時にはこれらのTODOを全部消化するか、もしくは別ファイル（たとえばTODO.md）に避難して、コード中のTODOを全部消します。

## ソースコードのbuild

testが通ったコードをそのまま公開する場合もあると思いますが、`development`、`production`のように開発用と本番用を分けている場合は本番用のビルドを忘れないように。  

当然リビルドしたコードがtestを通るかの確認も。

## GitHubにpushしてCI(travis等)のtest

私は「GitHubはベータ版も公開する場所」と考えています。  

npmにpublishしたモジュールは以下のコマンドでインストールできます。

```
npm install <パッケージ名>
```

しかし以下のコマンドを使うと、GitHubから直接インストールできます。

```
npm install <GitHubのユーザー名>/<リポジトリ名>
```

とはいえ後者はあまり使われていないと思います。  
あくまでも「npmのmoduleはnpmjs.comから取得する」というのが基本です。

- npmはStableバージョンのみ置く
- GitHubはStableもBetaも置く

と私は考えています。

なので`npm publish`する前に必ずtravisでtestを通ることを確認します。


> [mick\-whats/ohlc\-node \- Travis CI](https://travis-ci.org/mick-whats/ohlc-node)

package.jsonに依存するmoduleをdependenciesに書き忘れていた(install時に --saveオプションを忘れていた)場合など、localではtestを通っても本番では失敗するかもしれません。なので必ずCIで確認を。


## npm versionの更新
`npm publish`を実行したときに、package.jsonのversionが更新されていないとエラーになります。  
これを防ぐためにversionを更新するためのコマンドがあります。

```shell
> npm version major
# v1.0.0 から v2.0.0 へ変更

> npm version minor
# v1.0.0 から v1.1.0 へ変更

>npm version patch
# v1.0.0 から v1.0.1 へ変更
```

これらのコマンドを実行すると`git tag <version>`と`git commit`まで実行してくれます。

## npm publish

ここまでOKならいよいよ`npm publish`します。おつかれさまでした。
Git用語集

git pull : 遠隔吸収
git pull --rebase : 整理して遠隔吸収
git commit : 委託
git add : 追加
git push origin master: 送信
git stash : 保存
git stash pop : 保存を破棄
git status : 状態
merge : 合流

混乱した時
git rebase --skip
iOSアプリが、環境によってDLサイズが違う理由

#iOSアプリが、環境によってサイズが違う理由

## なぜ異なるのか
AppStoreに関連したipaファイルは大きく分けて3種類あり、状況によってそのどれかに該当するからです。(当たり前ですね)
※adhocとかenterpriseはここでは言及しません

### 審査提出用にXCodeでビルドしたもの
ここ最近のSDKでビルドすると、このタイプは非常に大きくなります。理由はシンプルで、AppStoreのためにデバッグシンボルなど可能な限りのデータが同梱されるからです。

### ユニバーサルipa
旧来のアプリです。webで検索した時出る容量もこの値が使われます。全ての機種向けに最適化され、AppStoreのために添付したデータが除去されています。

### App Thinning済みipa
iOS9以降のデフォルトです。前項のものからさらに最適化として、DLしたデバイスに不要なものが除去されます。したがって、機種ごとに異なるサイズになる可能性があります。(少なくともユニバーサルipaよりも小さくなります)

## 審査提出前にiOS8以前,9以降の概算値が知りたい
iOS8以前、iOS9以降の容量は審査提出し、通過するまで知ることができません。ですが、概算値はXCodeのレポート機能で知ることができます。
詳しいやり方は本記事末尾にあるリンクをご覧ください。(他力本願)

## 参考
- [[iOS] 新規インストール時のアプリサイズを計測し、最適化を行なう方法について](https://dev.classmethod.jp/smartphone/reducing-the-size-of-ios-app/)
Ruby 環境構築


#注意
どこを参照しているのか見てみる

`/usr/bin/ruby`はシステム権限のためダメ

```
$which ruby
/usr/bin/ruby
```

正しくは

```
$which ruby
/Users/[ユーザ名]/.rbenv/shims/ruby
```


##参考

https://prog-8.com/docs/ruby-env
watson studioのJupyter notebookからdb2へアクセス

# はじめに
Watson StudioからDB2のデータをDataframeに落としたいことがあったので、その手順のメモ。
おそらくWatson Stduio以外の汎用的なJupyterの環境ではdb2関係のライブラリの追加導入が必要なのではと思います。


```py3
import ibm_db
import ibm_db_dbi
import pandas as pd

# 以下の変数は環境に応じて個別設定して下さい

# データベース名
dbname = 'xxx'
# ホスト名
hostname = 'xxx'
# ポート番号
port = 'xxx'
# 接続ユーザー名
uid = 'xxx'
# 接続パスワード
pwd = 'xxx'

# 接続用パラメータの生成
conn_params = 'DATABASE=%s;HOSTNAME=%s;PORT=%s;PROTOCOL=TCPIP;UID=%s;PWD=%s;' % (dbname, hostname, port, uid, pwd)

con = ibm_db.connect(conn_params, "", "")
conn = ibm_db_dbi.Connection(con)

# 次のSQL文は要件に応じて書き換えて下さい
sql = "select * from CAR_RENTAL_TRAINING"

# データフレームに検索結果の読み込み
df = pd.read_sql(sql, conn)

# 結果の確認
df.head()
```

うまくできると、こんな感じでデータベースの内容がDataFrameに取り込まれているのがわかります。

![スクリーンショット 2018-10-01 12.22.33.png](https://qiita-image-store.s3.amazonaws.com/0/206130/b78eabea-244c-561e-c131-d1d9b9dc1910.png)
ワーディングを定義したcsvをAndroidのstring.xmlに変換するperlスクリプト

前書き
-
昔のメモを整理中、個人的に使い勝手良いコードあったので備忘録としてQiitaにも貼っておきます。
なぜperlで書いたのかはよくわからんですね。なんとなく、そのときの気分でしょう。

文言管理と、コーディングを分けるときとか、iOSとワーディング共通化管理するときにこういうの使うと良いはず。というか、夏頃にとった3連休あたりでこれ発掘していれば、前のプロジェクトの文言管理もっと楽できた。。。

あと、iOS向けのファイル生成処理とかCSVのフォーマット生成とか、気が向いたら組み込んでみるかも。
タイトル行の読み飛ばしとかも引数で設定できればもっと良いですね。それと多言語の文言管理なんかも。
まぁ、そのうちに。

注意事項
-
csvの形式に合わせて、配列からkey,value取り出すindex変えてください。変える場所はkeyとかvalueで検索すればわかると思います。

```
#!/usr/bin/perl
use strict;
use Text::ParseWords;

# 引数の処理
my $file = shift;
my $str = "    <string name=\"{key}\">{value}</string>\n";

my $output_en = "string_en.xml";

print $file;

unless ($file) {
  # 引数がないときは、使用方法を示して終了。
  die "Usage: $0 file"; 
}

# ファイルを解析してcsv形式のデータを配列に変換。
my @recs = parse_file($file);

open(FILE, "> $output_en") or die "$!";

print FILE "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n";

foreach my $items (@recs) {
#print @$items;
    my $string = $str;
	$string =~ s/{key}/@$items[0]/g;
	$string =~ s/{value}/@$items[2]/g;

    print FILE $string;
}

print FILE "</resources>";

close(FILE);

# ファイル解析用の関数
sub parse_file{
  my $file = shift;
    
  open(my $fh, "<", $file)
    or die "Cannot open $file for read: $!";
    
  # 配列に変更
  my @recs;
  while (my $line = <$fh>) {
#   print $line;
    # 改行を取り除く
    chomp $line; 
      
    # 配列に変更
    my @items; 
#   @items= split(/,/, $line);
    @items = &parse_line(',',undef, $line);

    # pushするときに、[ ]でリファレンスを作成。 
#   print @items;
    push @recs, [@items]; 
  }
  close $fh;    
  return @recs; 
}
```
sftpでchrootの設定をする。

# はじめに
AmazonLinux2にsftpユーザーにchrootを設定する手順をまとめました。


# 事前準備
設定する前の事前準備です。

## ユーザー作成
まず、sftpuserという名前でユーザーを作成します。

```bash:ユーザー作成
$ sudo useradd sftpuser
$ sudo passwd sftpuser
```

## ディレクトリの作成
次にchroot用のディレクトリを作成します。

```bash:
$ sudo mkdir /opt/chroot
$ sudo chown root.root /opt/chroot
$ sudo mkdir /opt/sftpuser
$ sudo chown sftpuser /opt/sftpuser/data
$ sudo chmod 755 /opt/sftpuser/data
```

chroot先のディレクトリの所有者はrootにする必要があります。
そのためファイルのアップロード用に配下にディレクトリを作成しています。


# 設定
準備ができたので設定を行います。

## config修正
既存のconfigのバックアップを取り、修正します。

```bash:
$ sudo cp -pi /etc/ssh/sshd_confg /etc/ssh/sshd_config.bk
$ sudo vim /etc/ssh/sshd_config
```

`Subsystem sftp  /usr/libexec/openssh/sftp-server`の行があればコメントアウトをし、以下の内容を追加します。

```text:追加
Subsystem sftp  internal-sftp
Match User sftpuser
    ChrootDirectory /opt/sftpuser
    X11Forwarding no
    AllowTcpForwarding no
    PasswordAuthentication yes
    ForceCommand internal-sftp
```

| パラメータ                | 内容                  |
|---                     |---                    |
| ChrootDirectory        | chrootを行うディレクトリパス |
| X11Forwarding          | X11転送許可設定         |
| AllowTcpForwarding     | TCP転送許可設定         |
| PasswordAuthentication | パスワード認証を行うか      |
| ForceCommand           | 強制コマンド設定          |

ユーザー単位でなくグループ単位にしたい場合は`User`を`Group`にします。


## sshd再起動
設定したら再起動します。

```bash:
$ sudo systemctl restart sshd.service
$ sudo systemctl status sshd.service
```

# 確認
それではsftpコマンドを使って実際にファイルのアップロードができるか試してみます。

```bash:
$ touch test
$ sftp sftpuser@localhost
sftp> cd data
sftp> put test
sftp> ls
sftp> rm test
sftp> ls
sftp> quit
```

ファイルのアップロードが確認できました。


# おわりに
rootでないとchrootできないにも関わらず、root権限がないのでファイルアップロードができないなんてなんか腑に落ちないです。。。

参考
https://euske.github.io/openssh-jman/sshd_config.html
spglibの使い方

クロスアビリティ [Winmostar](https://winmostar.com/jp/)サポートチームです。

#0. はじめに
結晶系の第一原理計算を実施する場合、事前に対象となる結晶の対称性を把握する必要がある。また、計算セルをPrimitiveセルへと変換しなければならない。しかしながら、比較的に大きなユニットセルを有する結晶においては、空間群を特定してPrimitiveセルを抽出することは容易ではない。少なくとも、手作業ではまず不可能である。本記事では、任意の結晶について、その対称性および空間群に関する処理を遂行するライブラリー"spglib"を紹介する。


#1. spglib
spglibはBSDライセンスにて、以下のURLからダウンロードできる。

https://atztogo.github.io/spglib/

当該ライブラリーのコンパイルおよびインストール方法については、このURLを参照のこと。この記事では、spglibライブラリーの使い方について解説する。C言語、Fortran、Python、Rubyのインターフェースが用意されているが、ここではC言語を対象とする。


#2. 空間群の特定
結晶の対称性を解析して、その空間群を特定するには、spglibのspg_get_datasetを使用する。サンプルコードは、以下の通り。spg_get_dtasetにてSpglibDatasetを取得を取得した後、これをSpglibSpacegroupTypeに変換。そこから、空間群のテーブル番号および対称性記号を取得している。入力データのlatticeは格子ベクトル、positionは計算セル内の原子座標、typeは原子種類を識別する番号、natomは原子の総数、symprecは対称性判定の閾値である。

``` c
void find_spacegroup(double lattice[3][3], double position[][3], int[] type, int natom, double symprec)
{
    SpglibDataset* dataset;
    dataset = spg_get_dataset(lattice, position, type, natom, symprec);

    SpglibSpacegroupType spgtype;
    spgtype = spg_get_spacegroup_type(dataset->hall_number);

    printf("Table Number => %d\n",  spgtype.number);
    printf("International => %s\n", spgtype.international);
    printf("Hall symbol => %s\n",   spgtype.hall_symbol);
    printf("Schoenflies => %s\n",   spgtype.schoenflies);

    spg_free_dataset(dataset);
}
```


#3. Primitiveセルへの変換
計算セルをPrimitiveセルに変換する場合には、spg_standardize_cellを使用する。サンプルコードは、以下の通り。spg_standardize_cellの戻り値は、Primitiveセル内の原子数である。入力データは任意の計算セルに対する値である。Conventionalセルやスーパーセルを入力データとすることができる。lattice、position、typeはPrimitiveセルの値に上書きされる。

``` c
void convert_to_primitive(double lattice[3][3], double position[][3], int[] type, int natom, double symprec)
{
    int nprim;
    nprim = spg_standardize_cell(lattice, position, type, natom, 1, 0, symprec);
}
```

逆に、PrimitiveセルをConventionalセルに変換する場合には、以下のコードである。このとき、原子数が増大する可能性があるため、positionおよびtypeの配列次元はnprimの4倍とする必要がある。

``` c
void convert_to_conventional(double lattice[3][3], double position[][3], int[] type, int nprim, double symprec)
{
    int natom;
    natom = spg_standardize_cell(lattice, position, type, nprim, 0, 0, symprec);
}
```
pandas で Excelファイル(*.xlsx) の読み書き

## xlsx の作成

```py:xlsx_create.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	xlsx_create.py
#
#					Oct/01/2018
# ------------------------------------------------------------------
import sys
import pandas as pd
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
df = pd.DataFrame([
		["t1271","千葉",59476,"2003-9-21"],
		["t1272","勝浦",49573,"2003-3-14"],
		["t1273","市原",29471,"2003-6-25"],
		["t1274","流山",39872,"2003-8-28"],
		["t1275","八千代",27176,"2003-10-5"],
		["t1276","我孫子",13175,"2003-1-15"],
		["t1277","鴨川",85134,"2003-12-21"]])

print(df)
#
path="./cities.xlsx"
#
df.to_excel(path,header=False,index=False)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

## xlsx の読み込み

```py:xlsx_read.py
#! /usr/bin/python
#
#	xlsx_read.py
#
#					Jul/31/2024
# ------------------------------------------------------------------
import sys
import pandas as pd
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
file_xlsx = "./cities.xlsx"
#
df=pd.read_excel(file_xlsx,header=None)
print(df)
print(df.head())
#
df.to_csv("tmp001.csv",header=None,index=None)
df.to_json("tmp001.json",orient='records')
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行結果

```text
$ ./xlsx_read.py
*** 開始 ***
       0    1      2           3
0  t1271   千葉  59476   2003-9-21
1  t1272   勝浦  49573   2003-3-14
2  t1273   市原  29471   2003-6-25
3  t1274   流山  39872   2003-8-28
4  t1275  八千代  27176   2003-10-5
5  t1276  我孫子  13175   2003-1-15
6  t1277   鴨川  85134  2003-12-21
       0    1      2          3
0  t1271   千葉  59476  2003-9-21
1  t1272   勝浦  49573  2003-3-14
2  t1273   市原  29471  2003-6-25
3  t1274   流山  39872  2003-8-28
4  t1275  八千代  27176  2003-10-5
*** 終了 ***
```

## 次のバージョンで確認しました。

```text
$ python
Python 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas as pd
>>> pd.__version__
'2.1.4'
```
改行コード(\n)が含まれる文字列をブラウザの表示上で改行表示させる方法

## はじめに
HTMLタグの要素内容として、改行コードを含む文字列を埋め込んだ場合に改行の見せ方をブラウザ側で調整する方法がわかりました。
vue.jsを使用したプロジェクトなのでVue.jsのコンポーネントを使用していますが、vue.jsとかmustache記法は関係ありません。


## 困っていること
何もしないと、こんな感じになります。
エラーメッセージとはいえ、美しく表示させたいのでエラーメッセージ毎に改行表示させたい。
JS側のコードになるべくHTMLタグを入れ込みたくない。

* 実行結果

![error1.png](https://qiita-image-store.s3.amazonaws.com/0/296075/52f18daa-808d-517e-4f98-5c0f68021a9e.png)

* サンプルコード

``` html
<template>
  ...
  <strong>Error:&nbsp;{{message}}</strong>
  ...
</template>
<script>
export default {
  data() {
    return {
      message: `User nameは必須項目です。
                E-mailは必須項目です。
                New passwordは必須項目です。`
    }
  }
}
</script>
```

## 解決方法
### CSSまたはStyle属性にCSS属性「white-space」を指定する。
### white-spaceとは
* 空白文字(半角スペースやタブ、改行など)をブラウザでどのように扱うか指定する際に使用する。
* 指定例
  * 連続する空白を詰めて表示する or そのまま残して表示する
  * 右端で自動的に折り返す or \<br>で改行するまで折り返さない

### 指定方法

|#|指定方法|説明|
|--:|:--|:--|
|1|white-space: normal|連続する空白文字を1つの半角スペースとして表示する。ボックス右端で自動的改行される。|
|2|white-space: nowrap|連続する空白文字を1つの半角スペースとして表示する。\<br>で改行するまで折り返さない|
|3|white-space: pre|連続する空白文字をそのままの状態で表示する。\<br>で改行するまで折り返さない
|4|white-space: pre-wrap|連続する空白文字をそのままの状態で表示する。ボックス右端で自動的に改行される。|
|5|white-space: pre-line|改行以外の連続する空白文字を1つの半角スペースとして表示する。改行(\nなど)は改行表示される。ボックス右端で自動的改行される。|

* さらに
CSS属性「word-wrap:break-word」を設定すると、ブラウザが単語境界を考慮して折り返してくれる。

## 解決方法を適用した結果
今回は「white-space: pre-wrap」と「word-wrap:break-word」を指定しました。

* 実行結果

![error2.png](https://qiita-image-store.s3.amazonaws.com/0/296075/444c93e5-8692-bbb5-91a9-e2b09673428f.png)

* サンプルコード

``` html
<template>
  ...
  <strong style="white-space:pre-wrap; word-wrap:break-word;">Error:&nbsp;{{message}}</strong>
  ...
</template>
<script>
export default {
  data() {
    return {
      message: `User nameは必須項目です。
                E-mailは必須項目です。
                New passwordは必須項目です。`
    }
  }
}
</script>
```
Rails:migrateでDBをリセットして最初からつくり直す方法。

開発途中にDBを全てリセットをする必要があったため、
備忘録を含め記録として残したいと思います。


####①全てのレコードを空にしたい場合は`rake db:reset`を行う。

`rake db:reset`は全てのテーブルを dropし、`"db/schema.rb" `を元にテーブルの再作成を行います。


####②`"db/migrate/"` 以下の全ての migration を実行してテーブルを再作成したい場合は、`rake db:migrate:reset`

全てのテーブルを dropし`"db/migrate/"`以下の全ての migration を実行してテーブルを再作成を行うため、こちらの方が効力が強いかと思料されます。

ご参考になれば幸いです。
pandas で json の読み書き

## json の作成

```py:json_create.py
#! /usr/bin/python
#
#	json_create.py
#
#					Oct/01/2018
# ------------------------------------------------------------------
import sys
import pandas as pd
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
df = pd.DataFrame({'t0921': ["宇都宮",41295,"2003-8-12"],
		't0922': ["小山",41298,"2003-8-12"],
		't0923': ["佐野",31925,"2003-5-20"],
		't0924': ["足利",57418,"2003-4-18"],
		't0925': ["日光",71696,"2003-7-9"]},
	index=['name', 'population', 'date_mod'])

print(df)
#
path="./cities.json"
#
df.to_json(path)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

作成される json

```json:cities.json
{
  "t0921": {
    "name": "宇都宮",
    "population": 41295,
    "date_mod": "2003-8-12"
  },
  "t0922": {
    "name": "小山",
    "population": 41298,
    "date_mod": "2003-8-12"
  },
  "t0923": {
    "name": "佐野",
    "population": 31925,
    "date_mod": "2003-5-20"
  },
  "t0924": {
    "name": "足利",
    "population": 57418,
    "date_mod": "2003-4-18"
  },
  "t0925": {
    "name": "日光",
    "population": 71696,
    "date_mod": "2003-7-9"
  }
}
```

## json の読み込み

```py:json_read.py
#! /usr/bin/python
#
#	json_read.py
#
#					Oct/01/2018
# ------------------------------------------------------------------
import sys
import pandas as pd
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
file_json = "./cities.json"
#
df=pd.read_json(file_json)
print(df)
#
df.to_json("tmp001.json")
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行結果

```text
$ ./json_read.py
*** 開始 ***
                t0921      t0922      t0923      t0924     t0925
date_mod    2003-8-12  2003-8-12  2003-5-20  2003-4-18  2003-7-9
name              宇都宮         小山         佐野         足利        日光
population      41295      41298      31925      57418     71696
*** 終了 ***
```

## 確認したバージョン

```text
$ python
Python 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas
>>> pandas.__version__
'2.1.4'
```
pandas で csv の読み書き

csv の作成

```py:csv_create.py
#! /usr/bin/python
#
#	csv_create.py
#
#					Oct/01/2018
# ------------------------------------------------------------------
import sys
import pandas as pd
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
df = pd.DataFrame([
		["t1271","千葉",59476,"2003-9-21"],
		["t1272","勝浦",49573,"2003-3-14"],
		["t1273","市原",29471,"2003-6-25"],
		["t1274","流山",39872,"2003-8-28"],
		["t1275","八千代",27176,"2003-10-5"],
		["t1276","我孫子",13175,"2003-1-15"],
		["t1277","鴨川",85134,"2003-12-21"]])

print(df)
#
path="./cities.csv"
#
df.to_csv(path,header=None,index=None)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

次の csv が作成されます。

```text:cities.csv
t1271,千葉,59476,2003-9-21
t1272,勝浦,49573,2003-3-14
t1273,市原,29471,2003-6-25
t1274,流山,39872,2003-8-28
t1275,八千代,27176,2003-10-5
t1276,我孫子,13175,2003-1-15
t1277,鴨川,85134,2003-12-21
```

csv の読み込み

```py:csv_read.py
#! /usr/bin/python
#
#	csv_read.py
#
#					Oct/01/2018
# ------------------------------------------------------------------
import sys
import pandas as pd
#
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
file_csv = "./cities.csv"
#
df=pd.read_csv(file_csv,header=None)
print(df)
print(df.head())
#
df.to_csv("tmp001.csv",header=None,index=None)
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行結果

```text
$ ./csv_read.py 
*** 開始 ***
       0    1      2          3
0  t1271   千葉  59478  2003-9-21
1  t1272   勝浦  49573  2003-3-14
2  t1273   市原  29179  2003-6-25
3  t1274   流山  39872  2003-8-28
4  t1275  八千代  29176  2003-10-5
5  t1276  我孫子  29176  2003-10-5
6  t1277   鴨川  29176  2003-10-5
       0    1      2          3
0  t1271   千葉  59478  2003-9-21
1  t1272   勝浦  49573  2003-3-14
2  t1273   市原  29179  2003-6-25
3  t1274   流山  39872  2003-8-28
4  t1275  八千代  29176  2003-10-5
*** 終了 ***
```

## 確認したバージョン

```text
$ python
Python 3.12.3 (main, Apr 10 2024, 05:33:47) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas
>>> pandas.__version__
'2.1.4'
```
GitHub pages/Netlifyにおけるreactルーティングまとめ

CRAで作ったreactアプリを

- GitHub pages
- Netlify

で公開してみたときに気づいたまとめです。

# サービスによるルーティング設定の違い
## GitHub pages

`pushState`への対応方法

1. `pushState`を使わずhashRouter(#など)を使う
2. routeパスに`{process.env.PUBLIC_URL}`を追加する。

[Gh-pages deployment problems with react-router](https://github.com/facebook/create-react-app/issues/1765)

## Netlify
`pushState`への対応方法

1.publicフォルダに以下の内容の`_redirects`ファイルを作成する。

```txt
/*    /index.html   200
```

[History Pushstate and Single Page Apps](https://www.netlify.com/docs/redirects/#history-pushstate-and-single-page-apps)


初めてnetlify使ったのですが、以下の記事を参考にさせていただきました。

- [高機能ホスティングサービスNetlifyについて調べて使ってみた](https://qiita.com/TakahiRoyte/items/b7c4d1581df1a17a93fb)
- [静的サイトを公開するならどこがいいの？](https://nabettu.hatenablog.com/entry/staticsite)
- [Netlityを用いた静的サイトのホスティング](https://qiita.com/_Keitaro_/items/44cc974140a5b99fb6cc)
redmineのプラングイン DSMF と Worktime を共存させる方法

# はじめに

Redmineのプラグインとして、文書管理のDSMF（redmine_dsmf）と、時間管理のworktime（redmine_dsmf）を共存させようとして苦労した話。
それぞれの根本原因は切り分けできてませんが、対応記録としてメモです。

# 環境

* CentOS-7 + appache-2.4 + passenger
* rails-4.2.8
* redmine-3.4.6 
* DSMF-1.6.1 　https://www.redmine.org/plugins/dmsf
* worktime-0.3.4 　https://www.redmine.org/plugins/redmine_work_time

# 手順

## 初期状態

DSMFがインストール済で稼働中

## worktimeのインストール

worktimeの最新版を　https://bitbucket.org/tkusukawa/redmine_work_time/downloads からダウンロードし、redmine/plugin 以下に展開。

ここでディレクトリ名を redmine_work_time とすべきところを redmine_work_time-0.3.4 のまま、以下のコマンドでDBマイグレートしてまう。

```
rake redmine:plugins:migrate RAILS_ENV=production
```

## トラブル１：translation missing:

Redmineをリスタートすると、「translation missing: ja.redmine_work_time」と表示される。これはプラグイン名とディレクトリ名が一致していないのが原因で、ディレクトリ名を修正するだけで対策完了

## トラブル２：設定画面が500エラー

redmineのログ

```
SystemStackError (stack level too deep):
plugins/redmine_dmsf/lib/redmine_dmsf/patches/projects_helper_patch.rb:29:in `project_settings_tabs'
plugins/redmine_work_time/lib/work_time_projects_helper_patch.rb:14:in `project_settings_tabs_with_work_time'
```

ネット検索で以下のページ（ https://github.com/danmunn/redmine_dmsf/issues/845 )を参考に、plugins/redmine_dmsf/lib/redmine_dmsf/patches/projects_helper_patch.rb
の、project_settings_tabs を project_settings_tabs_without_banner に置き換えることでエラーは解消。

## トラブル３：プロジェクト作成／削除で500エラー

redmineのログ

```
redmine-3.4 Error: Table easy_setting doesn't exist
```

なぜか、easy_settingテーブルが無くなっていたので、redmine全体のマイグレーションを再実行で解消。

```
bundle exec rake db:migrate RAILS_ENV=production
```

## まとめ

詳細の原因分析をしていませんがこ問題なく動作しているようです。
Apple Watch 備忘録

Apple Watchを買ったので初めて使う人が躓きそうなことを備忘録的に記載しておきます。
定期的に更新予定。

iPhone(iOS):12.0
Apple Watch Series 3(watchOS):4.3.2

### push通知がこない

アプリによって来たり、来なかったりすることがあって困っていました。
iPhoneのアプリ通知設定からサウンドなど全てONにすれば届くようになります。
バナーのみ表示とかにしていると届かないと思います。
具体的な条件についてはわかり次第追加予定


### アプリ開発したい

通常のiPhoneアプリを開発する手順で、File->New->Target->watchOS->watchKitとすれば作れます。

### GPSモデルはiPhoneがなくてもどれくらい使える？

### 保護フィルム買ったほうがいい？

買って1日で傷が付いたので気になる人は買ったほうがいいです。

### 開発にオススメのサイト・書籍は？
SSL証明書の整合性チェック

クライアントが取得したSSL証明書をもらって、Nginxに設定する機会があり
念の為、サーバ証明書と中間証明書、秘密鍵の整合性をチェックして設定したのでメモ。

# 中間証明書を結合

```
cat [サーバ証明書].crt [中間証明書].crt [ルート証明書].crt > example.com.crt
```
（多分ルート証明書は結合する必要ないと思うけど）


# サーバ証明書と秘密鍵の整合性チェック

ハッシュ値が同じかチェック

```
$ openssl x509 -noout -modulus -in [サーバ証明書].crt | md5sum
fe63769fada85ad811f33a5782c15db6  -

$ openssl rsa -noout -modulus -in [秘密鍵].key | md5sum
fe63769fada85ad811f33a5782c15db6  -
```

# サーバ証明書と中間証明書の整合性チェック

ハッシュ値が同じかチェック

```
$ openssl x509 -issuer_hash -noout -in [サーバ証明書].crt
8d28ae65

$ openssl x509 -subject_hash -noout -in [中間証明書].crt
8d28ae65
```

# サーバ証明書の有効期限チェック

```
$ openssl x509 -noout -dates -in [サーバ証明書]
notBefore=Sep 28 00:00:00 2018 GMT
notAfter=Sep 28 23:59:59 2019 GMT
```
flutter doctorで「✗ Android license status unknown.」が出た場合

flutterやる時に以下が出たのでメモ。

```
$ flutter doctor
・・・
✗ Android license status unknown.
・・・
```

こうなった場合は、以下のコマンドで対応できます。

```
$ flutter doctor --android-licenses
```

その前にそもそもJDKを入れていない場合は、入れます。

自分はSDKMAN!で入れます。

```
$ curl -s "https://get.sdkman.io" | bash
```

以下のbash_profileを書き換えるシェルを呼べば、SDKMAN!は利用できるようになります。

```
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
$ source ~/.bash_profile
```

JDKをインストール

```
$ sdk install java 8.0.181-zulu
$ source ~/.bash_profile
```

SDKを取得。

```
$ ~/Library/Android/sdk/tools/bin/sdkmanager --update
```

これで終わり。

```
$ flutter doctor --android-licenses 
```
Xcode 10 libfishhook.a cannot be found

RTCWebSocket.xcodeproject -> RCTWebSocket -> Build Phasesを選択 -> Link Binary WithLibraried にlibfishhook.aを追加。すでに追加されている場合は削除して再追加

![image](https://user-images.githubusercontent.com/637225/41004316-d626d112-68ef-11e8-8a5e-397a55777bc4.png)

参考 : Xcode 10 libfishhook.a cannot be found(https://github.com/facebook/react-native/issues/19569)
'config.h' file not found

Xcode10でReactNative製アプリを動かそうとしたら起きたエラーです。

```bash
$ ls node_modules/react-native/
```
third-partyディレクトリが無いことをチェック

```bash
$ sh node_modules/react-native/scripts/ios-install-third-party.sh
$ cd node_modules/react-native/third-party/glog-0.3.4
$ ./configure
$ make  
$ make install  
```

参考 : 
Xcode 10: third-party: 'config.h' file not found (https://github.com/facebook/react-native/issues/19839)
No member named rip in darwin_arm_thread_state64

Xcode10でReactNativeをコンパイルし、有線経由で端末にアプリをインストールしようとしたら発生しました。

エラーが出ている行(signalhandler.cc)を編集することで解決しました。


``` objectivec
# この行でエラーが出ている
return (void*)context->PC_FROM_UCONTEXT;  
# 上の行を下の行のように書き換えるする
return (void*)context->uc_mcontext->__ss.__pc
```

参考 Problem with third-party in Xcode 10 building to iOS physical device : (https://github.com/facebook/react-native/issues/19839)
rails で外部URLへのリダイレクトがうまくいかない


外部ドメインのOAuthを利用するにあたって、ユーザーからのフォーム送信に対して認可画面のリダイレクトを返す、という実装を行っていました。
それがなぜか、リダイレクトが404になってしまう自体に・・・

# TL;DR
フォーム送信先で外部ドメインへリダイレクト処理を行う場合は、`form_with`に**`local: true`**オプションをつけよう

# 何がおきていたか
Chromeの開発者ツールでリクエストの詳細を覗いてみると・・・
`http://hogehoge.com`からの302レスポンスを受け取ったあと、`http://fugafuga.com`に対して、`OPTIONS`というHTTPメソッドでリクエストを送っていることがわかりました。
fugafuga.com側ではそのURLに対するOPTIONSのルートを用意していなかったため、404エラーが発生したわけです。

## CORSのpreflightが発生しているっぽい
`OPTIONS`は、`CORS`リクエストの`preflight`という仕組みで使われるHTTPメソッドのようです。
参考：[CORSまとめ](https://qiita.com/tomoyukilabs/items/81698edd5812ff6acb34)
**preflight**リクエストでは、クロスドメインでAjaxリクエストを送る際に、「クロスドメインだけど、このページからリクエスト送っていいかい？」と確認をとるやりとりが発生します。
また、preflightリクエストを送るかどうかはHTTPの仕様に則ったブラウザの判断なので、原則、開発者が直接操作はできません。

## リダイレクトにCORSの仕組みが適用されている？？
上述の通り、CORSはAjax等でクロスドメイン通信する場合に適用される仕組みであり、今回のように302レスポンスでリダイレクトされる場合にpreflightリクエストが発生するのはおかしい。
これが今回の主なハマりポイントで、かつ、解決の糸口でした。

# 原因は、フォーム送信時のAjaxリクエスト
rails5.1の`form_with`を使用して今回のリクエストフォームを生成していました。
全く意識せず実装していたのですが、`form_with`はデフォルトで、フォーム送信にAjaxを用いるようです。（`form_tag`に`remote: true`を指定した状態）
参考：[【Rails 5】(新) form_with と (旧) form_tag, form_for の違い](https://qiita.com/hmmrjn/items/24f3b8eade206ace17e2)

おそらく、ブラウザは以下のような振る舞いを行っていたものと思われます。

```text
submitボタン押下に対し、Ajaxで`http://hogehoge.com`へPOSTリクエストを送る
　　↓
そのレスポンスとして、`http://fugafuga.com`への302リダイレクトを受け取る
　　↓
リダイレクト先へのリクエストもAjaxで送信しようとする（クロスドメインのためpreflightリクエストが発生する）
```

# フォーム送信に対して外部URLのリダイレクトをする場合はAjaxを使わせない
form_withのAjaxリクエストは、
以下のように、**`local: true`**オプションをつけることで回避（通常のSubmitさせる）可能です。

```slim:_form.html.slim
= form_with model: @hoge, url: tip_new_path, method: :post do |f|
```


# 補足：turbolinksを使っていれば回避可能
この問題、実はturbolinksを動かした状態だと発生しません。
turbolinksの効いている状態でいろいろと調べてみたところ、
- `redirect_to` で、status: 200の状態でJavaScriptのコードをレスポンス
- ブラウザで↑のJSを実行してリダイレクト
という挙動をしていました。
NeoVimでLSP(Language Server Protocol)を使ったら、定義ジャンプなどが劇的に早くなった

こんにちわ

vim8を使ってgoのコーディングをしていたのですが、
マシンパワー不足＆なぜかvimが重たくて、定義ジャンプなどが遅いのがかなりストレスだったので、
なんとか改善できないかと試行錯誤した結果、かなり早くになったので同じ状況に悩んでいる方がいたらぜひ試してみてください。

# アジェンダ
- [vim-goとLSPのスピード差異](#vim-goとlspのスピード差異)
- [環境](#環境)
- [導入](#導入)
- [LSPのデメリット](#lspのデメリット)
- [最後に](#最後に)

# vim-goとLSPのスピード差異
- vim-go
[![asciicast](https://asciinema.org/a/203830.png)](https://asciinema.org/a/203830)

- LSP(Language Server Protocol)
[![asciicast](https://asciinema.org/a/203836.png)](https://asciinema.org/a/203836)

vim-goによるジャンプがもっさりしているのに対して、
LSPはサクッとジャンプしているのは一目瞭然ですね。

ちゃんと調べていないのですが、vim-goの重たい原因はおそらく`guru`の範囲設定かと。

# 環境
- **機体**
MacBook Early 2015
CPU 1.2 GHz Intel Core M
メモリ 8 GB 1600 MHz DDR3

- **OS**
MacOS Mojave

- **Editor**
Neovim 0.3.1
※vim8でもLSP動きました

- **Plugin**
[dein](https://github.com/Shougo/dein.vim)
[vim-lsp](https://github.com/prabirshrestha/vim-lsp)
[vim-async](https://github.com/prabirshrestha/async.vim)

# 導入
LSPを導入するには以下の様に設定するだけです。
設定ファイルは[こちら](https://github.com/skanehira/nvim/tree/master/config/nvim)にあります。

- dein.toml

```toml
[[plugins]]
repo = 'prabirshrestha/async.vim'

[[plugins]]
repo = 'prabirshrestha/vim-lsp'
```

- init.vim

```vimscript
let mapleader = "\<Space>"

" 中略...

if executable('go-langserver')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'go-langserver',
        \ 'cmd': {server_info->['go-langserver', '-mode', 'stdio']},
        \ 'whitelist': ['go'],
        \ })
endif

nmap <silent> <Leader>d :LspDefinition<CR>
nmap <silent> <Leader>p :LspHover<CR>
nmap <silent> <Leader>r :LspReferences<CR>
nmap <silent> <Leader>i :LspImplementation<CR>
nmap <silent> <Leader>s :split \| :LspDefinition <CR>
nmap <silent> <Leader>v :vsplit \| :LspDefinition <CR>
```

# LSPのメリットとデメリット
- メリット
見ての通り、マシンのパワーがなくてもそれなりに早く動くところが最大のメリットだと思っています。

- デメリット
vim-goは`go run`、`go vet`、`go lint`など機能が豊富ですが、LSPは現時点で[以下](https://github.com/prabirshrestha/vim-lsp#supported-commands)の事しかできないようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/313dd7b6-92ab-17bc-21c4-c2cbd39b8300.png)

主にコーディング時に使用する

- 定義ジャンプ（画面分割も含め）
- インターフェイス実装検索
- 定義箇所検索

くらいかと思うので、vim-goの機能と組み合わせればそれなりにコーディングスピードが上がるのではないかなと。
`:LspNextError`などがあるようですが、いまいち使い方が分かっていないので知っている方いましたら教えて頂けると喜びます。

# 最後に
LSPが今後もっといろんな事ができるようになって行くと良いなと思いながら、気長に待とうと思います。
ちなみにvimでgoを書いている方で、こうすればもっと小コーディング捗るというのがあれば教えて頂けると喜びます。
なにどぞ…