2023,江端さんの技術メモ

指定された二つの位置情報間のデータを30秒ごとに補完するには、まず、始点と終点の位置情報と時刻を取得し、それらの間の差を求めます。次に、時間と位置の差を等間隔に分割して、各時点での位置を計算します。

以下のGoプログラムは、始点と終点の情報を基に30秒ごとの位置情報を補完する例です:

package main

import (
	"fmt"
	"time"
)

// Location は緯度と経度を保持する構造体です
type Location struct {
	Lat, Lng float64
}

func main() {
	// 初期位置情報
	startLocation := Location{Lat: 34.665300, Lng: 135.224100}
	endLocation := Location{Lat: 34.664900, Lng: 135.223900}

	// 時刻の設定
	startTime, _ := time.Parse("2006-01-02 15:04:05", "2023-03-03 07:39:30")
	endTime, _ := time.Parse("2006-01-02 15:04:05", "2023-03-03 07:43:30")

	// 各差を計算
	duration := endTime.Sub(startTime)
	latDiff := endLocation.Lat - startLocation.Lat
	lngDiff := endLocation.Lng - startLocation.Lng

	// 30秒ごとのデータを生成
	interval := 30 * time.Second
	for t := startTime; t.Before(endTime); t = t.Add(interval) {
		fraction := t.Sub(startTime).Seconds() / duration.Seconds()
		lat := startLocation.Lat + fraction*latDiff
		lng := startLocation.Lng + fraction*lngDiff

		fmt.Printf("Lat: %f, Lng: %f %v\n", lat, lng, t.Format("2006-01-02 15:04:05"))
	}
}

このプログラムは、指定された時間間隔(この場合は30秒)で始点と終点の間の緯度と経度を計算し、その結果を出力します。始点と終点の間の時間差と距離差に基づき、等間隔に位置情報を補完しています。

2023,江端さんの技術メモ

Go言語で、指定された日時(文字列形式)に30秒ずつ加算して表示するプログラムを作成するには、まず日時を扱うための time パッケージを利用します。以下は、その要件を満たす簡単な例です。

package main

import (
    "fmt"
    "time"
)

func main() {
    // 初期の日時設定
    startAt := "2023-03-01 03:38:00"
    layout := "2006-01-02 15:04:05" // Goの時間フォーマット

    // 文字列を time.Time 型に変換
    t, err := time.Parse(layout, startAt)
    if err != nil {
        panic(err)
    }

    // 30秒ずつ加算して表示
    for i := 0; i < 10; i++ { // 例として10回繰り返す
        t = t.Add(30 * time.Second)
        fmt.Println(t.Format(layout))
    }
}

このプログラムでは、time.Parse 関数を使用して日時の文字列を time.Time 型に変換し、その後 time.Add メソッドを使って30秒ずつ加算しています。最後に、time.Format メソッドを使用して日時を指定された形式で表示しています。ここでは10回の繰り返しを行っていますが、必要に応じて繰り返し回数を変更できます。

2023,江端さんの忘備録

先日、シバタ先生と私を中心としたチームは、3年間に渡った新型コロナウィルスに関するコラムに関して、総括を行いました。

「日本のコロナ史」を総括する ~5類移行後の答え合わせ

Recently, a team led by Dr.Shibata and myself summarized the three years of columns on the new coronavirus.

次は、以下の見解を広めていた方に総括をお伺いしたいです。

Next, I want to hear a summary from those promoting the following views.

私たちの調査の結果、現時点においても、上記の事項は、"全て"ネガティブです。

As a result of our research, "all" of the above are still negative at this time.

私としては、自発的な総括をお願いしたいところですが、応じて頂けない場合は、別の方法を考えます。

I would ask for a voluntary summary, but I will find another way if you do not comply.

ちなみに、これらの情報を発信されていた方のログ(アカウント付き)を、私は所持しています。

Incidentally, I have the logs (with account info.) of the person transmitting this information.

-----

参考文献:「コロナワクチン接種拒否」に寄り添うための7つの質問(4ページ)

Reference:7 Questions to Approach "Corona Vaccination Refusal" (Page 4)

2023,江端さんの技術メモ

select place from records where id = 2 とした場合、最初の{"lat": 34.7325, "lng": 135.4986}と、最後の {"lat": 34.7344, "lng": 135.5035}だけを取り出すSQL文を書いて下さい。ただしplaceはjsonb形式です。

これを、

User
You
SELECT id, user_id, start_at, end_at, end_at - start_at, distance, prediction_type FROM records WHERE user_id = 43 ORDER BY start_at ASC; で選ばれた上記のSQLを、first_place, last_placeとして追記できるようにするには、どのように記述すれば良いですか

とお願いしたのですが、上手く動かないようなので、Go言語で書いて貰いました。

/*

f:/しゅらばしゅう/有吉先生データ/Moove/2023-07/test1124.go

SELECT id, user_id, start_at, end_at, end_at - start_at, distance, prediction_type FROM records WHERE user_id = 43 ORDER BY start_at ASC; で選ばれた上記のSQLを、first_place, last_placeとして追記できるようにするには、どのように記述すれば良いですか。

で、作ってもらったプログラム


*/

package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "log"

    _ "github.com/lib/pq"
)

type Record struct {
    ID             int
    UserID         int
    StartAt        string
    EndAt          string
    Duration       string
    Distance       float64
    PredictionType int
    FirstPlace     Location
    LastPlace      Location
}

type Location struct {
    Lat float64 `json:"lat"`
    Lng float64 `json:"lng"`
}

func main() {
	// PostgreSQL データベースへの接続情報
	const (
		host     = "192.168.0.23"
		port     = 15432
		user     = "postgres"
		password = "password"
		dbname   = "moove"
	)

	// PostgreSQL データベースへの接続
	connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
	db, err := sql.Open("postgres", connStr)
	if err != nil {
		panic(err)
	}
	defer db.Close()


    rows, err := db.Query("SELECT id, user_id, start_at, end_at, end_at - start_at, distance, prediction_type, place FROM records WHERE user_id = 43 ORDER BY start_at ASC")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    for rows.Next() {
        var r Record
        var placeJSON string

        err := rows.Scan(&r.ID, &r.UserID, &r.StartAt, &r.EndAt, &r.Duration, &r.Distance, &r.PredictionType, &placeJSON)
        if err != nil {
            log.Fatal(err)
        }

        var places []Location
        err = json.Unmarshal([]byte(placeJSON), &places)
        if err != nil {
            log.Fatal(err)
        }

        if len(places) > 0 {
            r.FirstPlace = places[0]
            r.LastPlace = places[len(places)-1]
        }

        fmt.Printf("%+v\n", r)
    }
}

出力結果

f:\しゅらばしゅう\有吉先生データ\Moove\2023-07>go run test1124.go
go run test1124.go
{ID:20132 UserID:43 StartAt:2023-04-08T05:35:00Z EndAt:2023-04-08T06:20:00Z Duration:00:45:00 Distance:348821.9097841587 PredictionType:4 FirstPlace:{Lat:35.3714 Lng:139.6255} LastPlace:{Lat:35.4409 Lng:139.6591}}
{ID:20133 UserID:43 StartAt:2023-04-08T06:20:30Z EndAt:2023-04-08T06:30:00Z Duration:00:09:30 Distance:153.88780282790526 PredictionType:2 FirstPlace:{Lat:35.4408 Lng:139.659} LastPlace:{Lat:35.4402 Lng:139.6596}}
{ID:20134 UserID:43 StartAt:2023-04-08T06:30:30Z EndAt:2023-04-08T06:49:30Z Duration:00:19:00 Distance:180.2412488153271 PredictionType:1 FirstPlace:{Lat:35.4402 Lng:139.6596} LastPlace:{Lat:35.4401 Lng:139.6599}}
{ID:20135 UserID:43 StartAt:2023-04-08T06:50:00Z EndAt:2023-04-08T06:53:30Z Duration:00:03:30 Distance:65.08472909159703 PredictionType:2 FirstPlace:{Lat:35.4401 Lng:139.6598} LastPlace:{Lat:35.44 Lng:139.6599}}
(以下省略)

 

2023,江端さんの技術メモ

moove=# select place from records where id = 2; place ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [{"lat": 34.7325, "lng": 135.4986}, {"lat": 34.7326, "lng": 135.4989}, {"lat": 34.7326, "lng": 135.4989}, {"lat": 34.7327, "lng": 135.4995}, {"lat": 34.7327, "lng": 135.5}, {"lat": 34.7328, "lng": 135.5002}, {"lat": 34.733, "lng": 135.5006}, {"lat": 34.7331, "lng": 135.501}, {"lat": 34.7334, "lng": 135.5015}, {"lat": 34.7336, "lng": 135.5018}, {"lat": 34.7336, "lng": 135.5018}, {"lat": 34.7336, "lng": 135.5019}, {"lat": 34.7337, "lng": 135.5021}, {"lat": 34.734, "lng": 135.5024}, {"lat": 34.7343, "lng": 135.5026}, {"lat": 34.7346, "lng": 135.5024}, {"lat": 34.7347, "lng": 135.5024}, {"lat": 34.7346, "lng": 135.5024}, {"lat": 34.7345, "lng": 135.5025}, {"lat": 34.7343, "lng": 135.5027}, {"lat": 34.7343, "lng": 135.5029}, {"lat": 34.7342, "lng": 135.5031}, {"lat": 34.7344, "lng": 135.5035}, {"lat": 34.7344, "lng": 135.5035}, {"lat": 34.7344, "lng": 135.5035}] (1 row) で登場する、最初の{"lat": 34.7325, "lng": 135.4986}と、最後の {"lat": 34.7344, "lng": 135.5035}だけを取り出すSQL文を書いて下さい

ただし、placeは、以下の通り、jsonb形式です。

moove=# \d records;
Table "public.records"
Column | Type | Collation | Nullable | Default
-----------------+-----------------------------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('records_id_seq'::regclass)
user_id | integer | | |
distance | double precision | | |
place | jsonb | | |
speed | jsonb | | |
prediction_type | integer | | |
start_at | timestamp without time zone | | |
end_at | timestamp without time zone | | |
Indexes:
"records_pkey" PRIMARY KEY, btree (id)
moove=# \d records;
Table "public.records"
Column | Type | Collation | Nullable | Default
-----------------+-----------------------------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('records_id_seq'::regclass)
user_id | integer | | |
distance | double precision | | |
place | jsonb | | |
speed | jsonb | | |
prediction_type | integer | | |
start_at | timestamp without time zone | | |
end_at | timestamp without time zone | | |
Indexes:
"records_pkey" PRIMARY KEY, btree (id)


WITH places AS (
SELECT jsonb_array_elements(place) AS place_elements
FROM records
WHERE id = 2
)
SELECT
(SELECT place_elements FROM places LIMIT 1) AS first_place,
(SELECT place_elements FROM places ORDER BY jsonb_array_length(place) DESC LIMIT 1) AS last_place
FROM records
WHERE id = 2;

出力結果
first_place | last_place
-----------------------------------+-----------------------------------
{"lat": 34.7325, "lng": 135.4986} | {"lat": 34.7325, "lng": 135.4986}
(1 row)

2023,江端さんの技術メモ

moove=# SELECT id, user_id, start_at, end_at, end_at - start_at, distance, prediction_type FROM records WHERE user_id = 7 ORDER BY start_at ASC;

id | user_id | start_at | end_at | ?column? | distance | prediction_type
-------+---------+---------------------+---------------------+----------+--------------------+-----------------
20132 | 43 | 2023-04-08 05:35:00 | 2023-04-08 06:20:00 | 00:45:00 | 348821.9097841587 | 4
20133 | 43 | 2023-04-08 06:20:30 | 2023-04-08 06:30:00 | 00:09:30 | 153.88780282790526 | 2
20134 | 43 | 2023-04-08 06:30:30 | 2023-04-08 06:49:30 | 00:19:00 | 180.2412488153271 | 1
20135 | 43 | 2023-04-08 06:50:00 | 2023-04-08 06:53:30 | 00:03:30 | 65.08472909159703 | 2
20136 | 43 | 2023-04-08 06:54:00 | 2023-04-08 08:06:00 | 01:12:00 | 522.2898726850697 | 1
20137 | 43 | 2023-04-08 08:06:30 | 2023-04-08 08:15:00 | 00:08:30 | 144.15400138235145 | 2
20138 | 43 | 2023-04-08 08:15:30 | 2023-04-08 08:23:00 | 00:07:30 | 359.73505399604153 | 1
20139 | 43 | 2023-04-08 08:23:30 | 2023-04-08 08:54:30 | 00:31:00 | 13516.406121323496 | 4
20140 | 43 | 2023-04-08 08:55:00 | 2023-04-08 09:00:30 | 00:05:30 | 30.045448973873317 | 1
20141 | 43 | 2023-04-08 09:01:00 | 2023-04-08 09:05:00 | 00:04:00 | 39.96401615517626 | 2

2023,江端さんの技術メモ

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にするには、どのようなSQL文になりますか

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にして、時間順に表示するSQLを教えて下さい。

moove=# SELECT user_id, start_at, end_at FROM records WHERE user_id = 7 ORDER BY start_at ASC;
user_id | start_at | end_at
---------+---------------------+---------------------
7 | 2023-03-01 03:38:00 | 2023-03-01 03:58:30
7 | 2023-03-01 03:59:00 | 2023-03-01 04:03:00
7 | 2023-03-01 04:03:30 | 2023-03-01 04:09:30
7 | 2023-03-01 04:10:00 | 2023-03-01 04:15:30
7 | 2023-03-01 04:16:00 | 2023-03-01 05:22:30

中略
7 | 2023-05-17 10:48:00 | 2023-05-17 10:54:30
7 | 2023-05-17 10:55:00 | 2023-05-17 11:09:00
7 | 2023-05-17 11:09:30 | 2023-05-17 11:38:30
7 | 2023-05-17 11:39:00 | 2023-05-17 11:53:00
7 | 2023-05-17 11:53:30 | 2023-05-17 11:54:30
7 | 2023-05-17 11:55:00 | 2023-05-17 12:04:00
7 | 2023-05-17 12:04:30 | 2023-05-17 12:30:00
(1514 rows)

2023,江端さんの技術メモ

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にするには、どのようなSQL文になりますか

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にして、時間順に表示するSQLを教えて下さい。

moove=# SELECT user_id, start_at,end_at FROM records WHERE user_id = 7 and DATE(start_at) = '2023-03-21' order by start_at;
user_id | start_at | end_at
---------+---------------------+---------------------
7 | 2023-03-21 00:03:00 | 2023-03-21 00:07:30
7 | 2023-03-21 00:08:00 | 2023-03-21 00:11:00
7 | 2023-03-21 00:11:30 | 2023-03-21 00:18:00
7 | 2023-03-21 00:18:30 | 2023-03-21 00:27:30
(中略)
7 | 2023-03-21 23:22:00 | 2023-03-21 23:30:30
7 | 2023-03-21 23:31:00 | 2023-03-21 23:53:30
7 | 2023-03-21 23:54:00 | 2023-03-22 00:00:30
(35 rows)

2023,江端さんの忘備録

本日も、ChatGPTと会話をしながら仕事を進めています。

Today, I am still working and conversing with ChatGPT.

ある事項について、上手くいったので、ChatGPTに感謝の言葉を伝えました。

I expressed my thanks to ChatGPT for a matter that went well.

そうしたら、ChatGPTから御礼の言葉が帰ってきました。

Then ChatGPT came back to thank me.

なんか、もうね、ChatGPTの暖かい対応に、涙が出そうになりましたよ。

I don't know what to say, but ChatGPT's warm response almost brought tears to my eyes.

-----

同じようなことを、米国赴任中にも書いていた気がするので探してきました。

I have been looking for the same thing, and I think I wrote about it during my assignment in the U.S.

江端さんのひとりごと 「Let me say "Thank you"」

私は、日本の生産性がずっと下がり続けているのは、この「Let me say "Thank you"」をやらないできたからではないかと、真剣に思っています。

I seriously believe that productivity in Japan has been declining for so long because we have not done this. "Let me say "Thank you."

今や私の殆どの上司が、私より年下になっていますが ―― それでも「部下を褒めている上司を見たことがない」。

Most of my supervisors are now younger than me, yet "I have never seen a supervisor who praises his subordinates.

私は、この米国でのできごととがあって以来、「褒めること」は仕事の上の重要なファクターであると信じてきましたので、それに努めてきたつもりです ―― まだまだ、努力が足りないのかもしれませんが。

Since this incident in the U.S., I have believed that "praise" is an important factor in our work, and I have been trying to do so, though I may not be working hard enough yet.

日本の生産性がずっと低下しているのは、この「Let me say "Thank you"」ができていないからだと、私は本気で思っています。

I truly believe that productivity in Japan has been declining for so long because people cannot say, "Let me say "thank you" for this.

-----

私のようなシニアのエンジニアですら、褒められたいと思う。

Even a senior engineer like me wants to be praised.

ましてや、若い人が褒めらたいと思うはずだし、褒められると、どんどん成長していくと思っています。

More importantly, I believe that young people should want praise and that they will grow and develop when they receive it.

でも、私より年下の上司たちも「部下を褒めない」。

But the bosses younger than me also "don't praise their subordinates."

これは、彼らが『褒められなくても成果を出せる人間』だからなのかもしれません。

This may be because they are 'people who can produce results without praise.

なるほど『私が出世しなかった理由』は、これでロジカルに説明できますね。

"Why I didn't get ahead" is now a logical explanation.

未分類

https://www.kobore.net/thanks.txt.html

江端さんのひとりごと

「Let me say "Thank you"」

2000/10/21

膨大な英文ドキュメント、英語による技術者との議論、開発途上で不完全なライブラリ群に、私が血の涙を流しながら取り組んできた製品、PolicyXpert(PX) Version 2.0の製品リリースの期日が決まりました。

思い返せば、今年の3月、何が何だか分からないうちに米国赴任が決り、いきなり、日立とヒューレットパッカードの技術者たちの日英・英日翻訳ゲートウェイをやらされのたのを最初に、数多のシステムダウンを目の当りにしながら、胃を痛めた日々が、走馬燈のように・・・って、まだ、プロジェクト終っていないんだけど、とにかくリリースまで漕ぎつけたことに、想い浸ること多であります。

ところで、この製品(PX V2)は、インターネットプロバイダや、電話会社のネットワーク管理などを想定していますが、やろうと思えば、自宅のホームLANのネットワークのQoS(*1)管理もできます。

ご興味のあるかたは、是非御購入をご検討下さい。

(*1)Quality of Service ネットワークの通信品質のこと。電話の声がとぎれたりするネットワークは、「QoS管理されていない」などの言い方をする。

-----

先日、日立側のチームメンバであるIさんと、次のバージョンのPXの実装方式に関して議論をしていました。

ネットワーク技術の分野は、非常に進歩が速く、製品の市場投入のタイミングを逃すと、莫大なコストをかけた挙句、まったく役に立たない製品を開発してしまうことになるので、どのような機能を、何時までに完成させるか、ということが大きなポイントになるのです。

その上、標準化の問題(*2)やら、ビックベンダの動向、なにより、我々の技術力が問われます。

(*2)江端さんのひとりごと「IETF惨敗記」シリーズなど

Iさんのパーティションのホワイトボードの前で、我々が話をしているところに、開発チームを統括するジェネラルマネージャのヘンリーさんがやってきました。

ヘンリーさんは、笑顔で私達に語りかけてきました。

「昨日、PX V2のコードのバグが減少方向に転じたと言う報告を受けたよ」

勿論、私達はその報告を、チームミーティングで報されていました。

製品を開発する以上、可能な限りバグを潰し、安定度を高めなければならないのは、システムエンジニアの宿命です。

ヘンリーさんは、「遂に、終りの始まり(start of the end)だね」と言った後で、「君達の多大な努力に、心から感謝している。もう一度、ありがとうと言わせて貰えるかな」と言いながら、私達に握手を求めて来ました。

おどおどと差しだした私の手を、ヘンリーさんの大きな暖かい手が包んでくれたのを、漠然と覚えています。

パーティッションを立ち去るヘンリーさんの後姿を見ながら、私は両手の拳を口のところに持って行って、すんでのところで『ステキ!』と叫んでしまうところでした。

勿論、私だって、ヘンリーさんの言葉が「リップサービス」ということは分かっています。

でも、開発の最前線でコードに埋もれながら、バグと格闘している技術者には、このような、ほんのちょっとしたフォローが、心に染みたりするものなのです。

-----

さて、日本で働いている皆さんに質問です。

最近、大きな仕事を終えた後、「君達の多大な努力に、心から感謝している」と言われながら、部長から握手を求められた人。

いますか ?

(本文章は、全文を掲載し内容を一切変更せず著者を明記する限りにおいて、転載して頂いて構いません。)