2023,江端さんの技術メモ

バスのリアルタイム情報を格納するサーバを作ることになりました(経緯が色々あって)。

情報を提供しているサーバから、JSONを定期的に取りに行けばいいんだろう、とか思っていたのですが、このProtocol Bufferというデータ形式を、私は聞いたことがありません。

実際にデータを取得してセーブしてみたのですが、明らかにバイナリです。

しかも、どのエディタでも自動整形しない。ということは、どうやらテキストではない。

で、色々調べたのですが、どうも要領を得ないのですが、下の動画でやっと分かった気になりました。

乱暴に言えば、Protocol Buffersとは「圧縮されたJSON または XML(のようなもの)」です。

まあ、JSONもXMLもテキストメッセージで、しかも構造を保持したまま送信するので「通信効率悪そうだなぁ」と前々から思っていましたので、こういうものが必要となるのは分かります。

Googleが提供していることもあり、また、リアルタイム系のデータでは必要となるのは分かりますが ―― また、覚えることが増えたなぁ、と少々ウンザリしています。


とりあえず、Go言語で動かすことを目的として、ここまでの経緯を記載しておきます。

私の環境は、Windows10です。GOはインストール済みです

(1)https://protobuf.dev/downloads/ から "Latest Version" →  "*-win64.zip"

をダウンロード。私はC:\の直下に展開しました。

でもって、この両方のフォルダーにpathを通しておきました。必要なのは"protoc.exe"です。

(2)私の場合、C:\Users\ebata\protocol_bufferesというディレクトリを作って、そこにソースを展開することにしました。

とりあえず、main.goという名前でファイルを作っておきます(後で必要になります)

package main

import "fmt"

func main() {
	fmt.Println("Hello World!!")
}

さらに、person.proto という名前で、

syntax = "proto3";
package main;

message Person{
    string name = 1;
    int32 age = 2;
}

というファイルを作ります。これがxmlやらJSONのスタイルファイルにようなものです。

で、ここから、person.pb.goというファイルを作らなければならないのですが、これに苦労しました。

C:\Users\ebata\protocol_bufferesの中で、

$ protoc --go_out=. *.proto
protoc-gen-go: unable to determine Go import path for "person.proto"
Please specify either:
    • a "go_package" option in the .proto source file, or
      • a "M" argument on the command line.
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#p
ackage for more information.
--go_out: protoc-gen-go: Plugin failed with status code 1.

のようなことを繰り返していたのですが、person.proto の中に、一行追加したら、サクっと通りました。

syntax = "proto3";

option go_package="./;main"; // 理由は分からないけど、この1行で、以下のエラーが消えた

//$ protoc --go_out=. *.proto
//protoc-gen-go: unable to determine Go import path for "person.proto"
//Please specify either:
//        • a "go_package" option in the .proto source file, or
//        • a "M" argument on the command line.
//See https://developers.google.com/protocol-buffers/docs/reference/go-generated#p
//ackage for more information.
//--go_out: protoc-gen-go: Plugin failed with status code 1.

package main;

message Person{
    string name = 1;
    int32 age = 2;
}

この結果、以下のようなperson.pb.goが生成されました。

// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.26.0
// 	protoc        v4.22.2
// source: person.proto

package main

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type Person struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
	Age  int32  `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"`
}

func (x *Person) Reset() {
	*x = Person{}
	if protoimpl.UnsafeEnabled {
		mi := &file_person_proto_msgTypes[0]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *Person) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Person) ProtoMessage() {}

func (x *Person) ProtoReflect() protoreflect.Message {
	mi := &file_person_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Person.ProtoReflect.Descriptor instead.
func (*Person) Descriptor() ([]byte, []int) {
	return file_person_proto_rawDescGZIP(), []int{0}
}

func (x *Person) GetName() string {
	if x != nil {
		return x.Name
	}
	return ""
}

func (x *Person) GetAge() int32 {
	if x != nil {
		return x.Age
	}
	return 0
}

var File_person_proto protoreflect.FileDescriptor

var file_person_proto_rawDesc = []byte{
	0x0a, 0x0c, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04,
	0x6d, 0x61, 0x69, 0x6e, 0x22, 0x2e, 0x0a, 0x06, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x12, 0x12,
	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
	0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
	0x03, 0x61, 0x67, 0x65, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x3b, 0x6d, 0x61, 0x69, 0x6e, 0x62,
	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
	file_person_proto_rawDescOnce sync.Once
	file_person_proto_rawDescData = file_person_proto_rawDesc
)

func file_person_proto_rawDescGZIP() []byte {
	file_person_proto_rawDescOnce.Do(func() {
		file_person_proto_rawDescData = protoimpl.X.CompressGZIP(file_person_proto_rawDescData)
	})
	return file_person_proto_rawDescData
}

var file_person_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_person_proto_goTypes = []interface{}{
	(*Person)(nil), // 0: main.Person
}
var file_person_proto_depIdxs = []int32{
	0, // [0:0] is the sub-list for method output_type
	0, // [0:0] is the sub-list for method input_type
	0, // [0:0] is the sub-list for extension type_name
	0, // [0:0] is the sub-list for extension extendee
	0, // [0:0] is the sub-list for field type_name
}

func init() { file_person_proto_init() }
func file_person_proto_init() {
	if File_person_proto != nil {
		return
	}
	if !protoimpl.UnsafeEnabled {
		file_person_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*Person); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: file_person_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_person_proto_goTypes,
		DependencyIndexes: file_person_proto_depIdxs,
		MessageInfos:      file_person_proto_msgTypes,
	}.Build()
	File_person_proto = out.File
	file_person_proto_rawDesc = nil
	file_person_proto_goTypes = nil
	file_person_proto_depIdxs = nil
}

さて、ここで、

package main

import (
	"fmt"
	"log"

	"google.golang.org/protobuf/proto"
)

func main() {
	fmt.Println("Hello World!!")

	elliot := &Person{
		Name: "Elliot",
		Age:  24,
	}

	data, err := proto.Marshal(elliot)
	if err != nil {
		log.Fatal("Marshalling error", err)
	}

	fmt.Println(data)
}

とした上で、

$ go run main.go person.pb.go

をすると、

main.go:7:2: no required module provides package google.golang.org/protobuf/prot
o: go.mod file not found in current directory or any parent directory; see 'go h
elp modules'
person.pb.go:10:2: no required module provides package google.golang.org/protobu
f/reflect/protoreflect: go.mod file not found in current directory or any parent
directory; see 'go help modules'
person.pb.go:11:2: no required module provides package google.golang.org/protobu
f/runtime/protoimpl: go.mod file not found in current directory or any parent di
rectory; see 'go help modules'

というエラーがでてくるので、
$go mod init m
$ go get google.golang.org/protobuf/reflect/protoreflect
$ go get google.golang.org/protobuf/proto
$ go get google.golang.org/protobuf/runtime/protoimpl

を実行して、再度、

$ go run main.go person.pb.go

を行うと

Hello World!!
[10 6 69 108 108 105 111 116 16 24]

とい値が出力されます。

package main

import (
	"fmt"
	"log"

	"google.golang.org/protobuf/proto"
)

func main() {
	fmt.Println("Hello World!!")

	elliot := &Person{
		Name: "Elliot",
		Age:  24,
	}

	data, err := proto.Marshal(elliot)
	if err != nil {
		log.Fatal("Marshalling error", err)
	}

	fmt.Println(data)

	newElliot := &Person{}
	err = proto.Unmarshal(data, newElliot)
	if err != nil {
		log.Fatal("unmarshalling error: ", err)
	}

	fmt.Println(newElliot.GetAge())
	fmt.Println(newElliot.GetName())

}

のプログラムを実行すると、

$ go run main.go person.pb.go
Hello World!!
[10 6 69 108 108 105 111 116 16 24]
24
Elliot

となる。


動的バス情報フォーマット(GTFSリアルタイム)ガイドライン

やっと見つけた

ここからダウンロードすると、こんな感じのprotoファイルが得られます。

で、これを以下のように修正して、

として、

$ protoc --go_out=. *.proto

を実施すると、さくっとgtfs-realtime.pb.goができました。

ここまでできれば、後はクライアントを作れば、できるはずです。

問題は、どうやってサーバにアクセスするか、を考えれば、いくはずです。
(が、基本的に最後に動くまで、どうなるかは分からないですが)。


さて、今回の私の狙いは、

https://ckan.odpt.org/dataset/b_bus_gtfs_rt-yokohamamunicipal

の、リアルタイムデータを取得して保存しておくことです。

これは、こちらに記載されているように

URL: https://api.odpt.org/api/v4/gtfs/realtime/YokohamaMunicipalBus_vehicle?acl:consumerKey=[発行されたアクセストークン/YOUR_ACCESS_TOKEN]

なので、このデータを所得するためには、「発行されたアクセストークン」というのを貰う必要があります。これ、"f4954c3814b207512d8fe4bf10f79f0dc44050f1654f5781dc94c4991a574bf4"(江端ルールで変更済み)というやつになります。

これは、https://developer.odpt.org/ から、申請してメールで付与してもらえます(2日くらいかな)。これがないと、データの取得ができないので注意して下さい。

さて、ここから、とりあえず、この横浜市交通局の市営バスのバス関連リアルタイム情報を取得するコードを、https://gtfs.org/realtime/language-bindings/golang/ をパクって、ちょっと修正してみました。

私は、c:\Users\ebata\protocol_bufferes\gtfs-realtime というディレクトリを掘って、上記のページ通りのことを実施しました。

$ go get github.com/MobilityData/gtfs-realtime-bindings/golang/gtfs

$ go get google.golang.org/protobuf/proto

以下のファイルを作成しました(トークンは自分のものに置き替えて下さい)。エラーの出てくるところは、コメントアウトしています。

// https://gtfs.org/realtime/language-bindings/golang/

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/MobilityData/gtfs-realtime-bindings/golang/gtfs"
	proto "github.com/golang/protobuf/proto"
)

func main() {
	var (
		username = "xx@gmail.com" // 横浜市交通局の市営バスのサイトでは不要のようだからダミーを放り込んでおく
		password = "xx"           // (同上)
	)

	client := &http.Client{}
	req, err := http.NewRequest("GET", "https://api.odpt.org/api/v4/gtfs/realtime/YokohamaMunicipalBus_vehicle?acl:consumerKey=f4954c3814b207512d8fe4bf10f79f0dc44050f1654f5781dc94c4991a574bf4", nil)
	if err != nil {
		log.Fatal(err)
	}

	req.SetBasicAuth(username, password)
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}

	defer resp.Body.Close()
	if err != nil {
		log.Fatal(err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(body)

	feed := gtfs.FeedMessage{}
	err = proto.Unmarshal(body, &feed)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(feed)

	/*

		for _, entity := range feed.Entity {
			tripUpdate := entity.TripUpdate
			trip := tripUpdate.Trip
			tripId := trip.TripId
			fmt.Printf("Trip ID: %s\n", *tripId)
		}
	*/
}

で、fmt.Println(body) のところを表示するとこんな感じになっています。

[10 13 10 3 50 46 48 16 0 24 165 246 160 161 6 18 41 10 9 118 105 99 108 95 49 56 48 54 34 28 18 10 13 252 214 13 66 21 192 155 11 67 40 165 205 159 161 6 66 6 10 4 49 56 48 54 72 0 18 41 10 9 118 105 99 108 95 49 48 48 50 34 28 18 10 13 188 173 13 66 21 205 159 11 67 40 233 176 159 161 6 66 6 10 4 49 48 48 50 72 0 18 41 10 9 118 105 99 108 95 51 57 57 50 34 28 18 10 13 83 131 13 66 21 28 146 11 67 40 216 210 159 161 6 66 6 10 4 51 57 57 .....

fmt.Println(feed)は、こんな風に表示されます。

{{{} [] [] 0xc00013f800} 0 [] map[] gtfs_realtime_version:"2.0" incrementality:FULL_DATASET timestamp:1680358181 [id:"vicl_1806" vehicle:{vehicle:{id:"1806"} position:{latitude:35.459946 longitude:139.6084} timestamp:1680336549 occupancy_status:EMPTY} id:"vicl_1002" vehicle:{vehicle:{id:"1002"} position:{latitude:35.419662 longitude:139.62422} timestamp:1680332905 occupancy_status:EMPTY} id:"vicl_3992" vehicle:{vehicle:{id:"3992"} position:{latitude:35.378246 longitude:139.57074} timestamp:1680337240 occupancy_status:EMPTY} id:"vicl_1732" vehicle:{trip:{trip_id:"04117_12202301042041P01910" schedule_relationship:SCHEDULED} vehicle:{id:"1732"}.....

あとは、ここをパースすれば、必要な情報は取り出せるはずです。


さて、ここから ~/protocol_bufferes/gtfs-realtime に環境を作ってみます。

$go mod init m
$ go get google.golang.org/protobuf/reflect/protoreflect
$ go get google.golang.org/protobuf/proto
$ go get google.golang.org/protobuf/runtime/protoimpl

で、

こちらの環境でも、上記と同じ手続で、gtfs-realtime.pb.goを作り、

$ go run main.go gtfs-realtime.pb.go

を実施してみましたところ、

main.go:11:2: no required module provides package github.com/MobilityData/gtfs-realtime-bindings/golang/gtfs; to
add it:
go get github.com/MobilityData/gtfs-realtime-bindings/golang/gtfs
main.go:12:2: missing go.sum entry for module providing package github.com/golang/protobuf/proto; to add:
go mod download github.com/golang/protobuf

と言われたので、言われた通りのことを実施してみました

ebata@DESKTOP-P6KREM0 MINGW64 ~/protocol_bufferes/gtfs-realtime
$ go get github.com/MobilityData/gtfs-realtime-bindings/golang/gtfs
go get: added github.com/MobilityData/gtfs-realtime-bindings/golang/gtfs v1.0.0
でもって、
ebata@DESKTOP-P6KREM0 MINGW64 ~/protocol_bufferes/gtfs-realtime
$ go mod download github.com/golang/protobuf
再度やってみました。
$ go run main.go gtfs-realtime.pb.go
go: updates to go.mod needed; to update it:
        go mod tidy
ここも言われた通り、
$ go mod tidy
をやりました。
でもって、また繰り返しました。
$ go run main.go gtfs-realtime.pb.go
panic: proto: file "gtfs-realtime.proto" is already registered
        previously from: "github.com/MobilityData/gtfs-realtime-bindings/golang/gtfs"
        currently from:  "main"
See https://protobuf.dev/reference/go/faq#namespace-conflict
goroutine 1 [running]:
google.golang.org/protobuf/reflect/protoregistry.glob..func1({0xea9240, 0xeb92b8}, {0xea9240, 0xc000058d70})
        c:/go/pkg/mod/google.golang.org/protobuf@v1.30.0/reflect/protoregistry/registry.go:56 +0x1f4
(以下、色々)
エラー文を見てみると、"gtfs-realtime.proto"が既に登録されている、とあります。
まあ、 ~/protocol_bufferes/ で、色々やったので、多分、登録してしまったのだろうと思います。
が、それを色々変えるのは面倒ですので、とりあえず対処方として、環境変数を変えてしまう、という手があるようです。
$ export GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn
で、ここの部分は回避できるようです(本格的な修正は後回しとします)。
とりあえず、エラーが出てこないように、main.goでコメントしていた部分を解いて、エラーが出てこないように修正しました。
feed := gtfs.FeedMessage{}
	err = proto.Unmarshal(body, &feed)
	if err != nil {
		log.Fatal(err)
	}
	//fmt.Println(feed)

	for _, entity := range feed.Entity {
		//tripUpdate := entity.TripUpdate
		fmt.Println(entity)
		fmt.Println()
		//trip := tripUpdate.Trip
		//tripId := trip.TripId
		//fmt.Printf("Trip ID: %s\n", *tripId)
	}
とりあえずentity(が、何かよく分からんのですが)を表示してみました。
この結果、以下のような表示が得られました。
id:"vicl_1780"  vehicle:{trip:{trip_id:"05406_09202304031054P00218"  schedule_relationship:SCHEDULED}  vehicle:{id:"1780"}  position:{latitude:35.415165  longitude:139.66798}  current_stop_sequence:10  stop_id:"5899_02"  current_status:IN_TRANSIT_TO  timestamp:1680534894  occupancy_status:EMPTY}
id:"vicl_3944"  vehicle:{trip:{trip_id:"03903_22202304031012A01309"  schedule_relationship:SCHEDULED}  vehicle:{id:"3944"}  position:{latitude:35.50719  longitude:139.55861}  current_stop_sequence:32  stop_id:"6219_01"  current_status:IN_TRANSIT_TO  timestamp:1680528244  occupancy_status:EMPTY}
id:"vicl_1705"  vehicle:{vehicle:{id:"1705"}  position:{latitude:35.378166  longitude:139.57071}  timestamp:1680522432  occupancy_status:FEW_SEATS_AVAILABLE}
id:"vicl_4607"  vehicle:{vehicle:{id:"4607"}  position:{latitude:35.492794  longitude:139.66455}  timestamp:1680526330  occupancy_status:NOT_ACCEPTING_PASSENGERS}
さて、次は、この内容を理解しなければなりません。
とりあえず、バスのID、緯度、経度が取れればよく、これでデータが取れるようです.
for _, entity := range feed.Entity {
			//tripUpdate := entity.TripUpdate
			//fmt.Println(entity)

			// データの読み込み
			uniName := *(entity.Vehicle.Vehicle.Id)
			lat := *(entity.Vehicle.Position.Latitude)
			lon := *(entity.Vehicle.Position.Longitude)

			fmt.Println(uniName, lat, lon)
}

2023,江端さんの忘備録

今夜、異動先の部署のキックオフの飲み会に参加してきました。

Tonight I attended the kick-off drinks for the department I am transferring to.

こんな私でも、節目の行事は、大切だと思っています。

『なんだかんだいって、セクショナリズムの対抗手段は、定期的な飲み会である』

Even I would like to cherish milestone events.

お開きのところで、挨拶を求められたので、一言だけ申し上げてきました。

At the close of the meeting, I was asked to say a few words.

「本日、聞いたお話は、3年間は『書きません』ので、ご安心下さい」

"I will not write about what I heard today for the next three years"

-----

一瞬、『この人、何を言っているの?』という風の顔の後で、「その"話"とは何だ?」と一斉につっこまれましたが、私はにこやかな笑顔を見せたまま、そのまま散会しました。

Just after everyone looked like, "What is he talking about?, they asked me "What is this 'talk'?" immidately. However, Smiling at them and I left soon.

今後は、節目の行事すら、呼ばれなくなるかもしれません。

In the future, I might not be called even milestone events.

2023,江端さんの忘備録

一年でもっとも嫌いな「月」を挙げろと言われれば、私は「4月」を挙げます。

If you ask me to name my least favorite "month" of the year, I will name "April".

■これまで動かなかった人々が、虫のようにわらわらと動き出すをの見るのが不快です。

- I am uncomfortable to see people who have never moved before start moving like insects.

■着なれないスーツを着て緊張した顔をしている若者が、これから挫折していくことになる現実に、気分が暗くなります。

- My mood darkens at the reality that these young men, looking nervous in their ill-fitting suits, are about to fall behind.

■この若者の中の何人かが、そう遠くない未来(とりあえずゴールデンウィークあたり)に出社しなくなり、さらに高い確率で、心の病に罹患することに憂鬱になります。

- I am depressed that some of these young people will stop coming to work in the not-too-distant future (around Golden Week for) and, at an even higher rate, will suffer from mental illness.

―― 国家レベルの「心の崩壊」が始まっている

そして、

And

■様々な人事発表で、私よりもはるかに若い人が、偉くなって、壇上から期首方針を述べているのを見るのは、気分の良いものではありません。

- It is not a pleasant feeling to see someone much younger than I am at various personnel announcements, rising to greatness and speaking from the podium about the policy for the term.

その度に、『彼と私は、何が違っていたのだろう?』と考えてしまう自分に自己嫌悪します。

Every time I do, I hate myself for thinking, 'What was so different about him and me?'

いや、判っているんですけどね。

Well, I know the reason well.

こちらのコラムでも、『あなたより優秀な後輩は、あなたの後に山ほど入社してきて、簡単にあなたの上司となります』と書いています。

In this column, I also wrote, 'A lot of juniors who are better than you will join the company after you, and they will easily become your boss.

ただ、頭では分かっているのですが、実際に知っている人が、どんどん出世(?)している様を見るのは、そこそこキツいものなのです。

I know this in my head, but it's hard to see someone I actually know moving up in the world.

-----

江端:「ついつい、『彼と私は、何が違っていたのだろう?』と考えてしまうんだよな」

Ebata: "I tend to think, 'What was different about him and me?'

嫁さん:「それは、もう『何もかも』でしょう」

Wife: "Needless to say, that would be 'everything'"

と嫁さんは言います。

My wife says,

「出世をする人は、会社に利益を与える人や、その気概を持っている人だけだよ」

The only people who get ahead are those who benefit the company and have the chutzpah to do so."

2020,江端さんの忘備録

以前の仕事の見直しが必要となっていますが、その作業を開始すると、その時の恐怖が再現されてきて、心臓がバクバクして、呼吸が苦しくなります。

I need to review my previous work. When you start the work, the fear at that time is reproduced, my heart beats, and breathing becomes difficult.

こういう症状が出るような場合、「初動」が大切なことは、自分でこれまで色々調べて知っていました。

I know that "initial response" is important, whenever I have such symptoms. Because I wrote about it in my columns.

すぐに、心療内科への電話予約を試みましたが、全ての医院で『初診は6月以降』と言われてしまいました。

Immediately, I tried to make a telephone reservation to several clinics of Department of Psychiatry and Internal Medicine, however at all the clinics I was told that my first visit was after June.

これも、連鎖的な医療崩壊の一端かもしれません。

This may also be part of the chain of medical collapse.

というか、

Rather, I am thinking that,

―― 国家レベルの「心の崩壊」が始まっている

The national level "disintegration of mental health" has begun

のかもしれないなぁ、と考えています。

2023,江端さんの忘備録

出生率の低下の一因(というか主要因)は、非婚化です。

One factor (or rather, the main factor) in the decline in the birth rate is the nonmarriage rate.

どうして、非婚化が進行しているかというと、その原因ははっきりしています。

The reasons for the growing number of unmarried people are clear.

―― 『結婚の価値、良さ、メリット』を、若者に対して言語化できない、私(たち)の無能

"My (our) inability to verbalize the "value, merits and advantages of marriage" to young people"

です。

-----

先日、ニュースで、『非婚女性のウェルビーイングが、既婚女性のウェルビーイングを越えたことが、統計で示された』という話を聞いて ―― 『いずれ、そのデータが出てくるだろう』とは予感していたのですが ―― それでも、ショックを受けています。

The other day I heard a story in the news that 'statistics show that the wellbeing of non-married women has surpassed that of married women' -- I had a hunch that 'eventually the data would come out' -- but... -- I was still shocked.

以下の表は、ちょうど10年前に私の予測した非婚化の予想です。

The following table shows my predictions of nonmarriage just 10 years ago.

私自身は、「非婚」が、価値のある人生の選択であることは、よく理解しています。

I myself understand that "non-marriage" is a worthwhile life choice.

しかし、同時に「結婚」もまた、価値のある人生の選択であることも知っています。

But at the same time, we know that "marriage" is also a worthwhile life choice.

-----

もちろん、非婚や結婚が、自分の選択だけで決まる訳ではありません。

Of course, non-marriage and marriage are not determined solely by one's choice.

しかし、現在が「結婚」が恐しく難しい時代であることは、データを見るまでもなく分かっています。

However, we don't need to look at the data to know that "marriage" is a terribly difficult time today.

以下のグラフは、10年前の私の予測です。ざっと見たところ、非婚化は、私の予測より加速されているようです。

The following graph is my prediction from 10 years ago. At a quick glance, it appears that the rate of nonmarriage is accelerating faster than I predicted.

現在の結婚の難しさは、私の体感で、私の時代の『10倍以上』は難しく、やろうと思えば、数値で叩き出せると思います。

The difficulty of marriage today is, in my experience, 'more than 10 times' as difficult as it was in my day, and I think I could beat it out of you numerically if I wanted to.

それはさておき。

Aside from that.

-----

『結婚の価値、良さ、メリット』を、若者に対して言語化できない、私(たち)無能 ―― について異議はないのですが ――

I have no objection of "My (our) inability to verbalize the "value, merits and advantages of marriage" to young people", however,

では、私たちの時代に、『結婚の価値を、きちんと言語化してくれた先人がいたか?』だろうか、と考えてみました。

So, in our time, 'Did any of our predecessors properly verbalize the value of marriage?' I wondered.

いや、いなかったぞ。

No, they weren't there.

たった一人を除いて、誰もいなかった。

There was no one there except for one person.

「結婚って、良いものですか?」

-----

では、私(たち)は、どうやって結婚を選択してきたのか?

So how have I(we) chosen to get married?

当時の人も、私たちと同様に、結婚の価値を言語化することはできなかったけど、『私は、結婚していた"その人"を信じることができた』とは言えると思うのです。

People then, like us, could not verbalize the value of marriage, but I think we can say, "I could believe in the 'person' who were married to".

では、"その人"とは誰か?

So, who is "the person"?

それは、親であり、先輩であり、高齢者であり、社会でした。

It was parents, seniors, the elderly, and society.

私(たち)は、結婚を支持する(または同調圧力をかけてくる)社会を、とりあえずは信じていたのです。

I (We) believed, for the time being, in a society that supported (or was sympathetic to) marriage.

-----

この考え方を拡張していくと ――

Extending this idea --

非婚化とは、

What is nonmarriage?

- 結婚を望まない人の価値観を認めず、

- Not recognize the values of those who do not wish to marry,

- 結婚を望む人の望みを叶えられない社会を作り(あるいは、その社会を放置し)、

- Create (or leave in place) a society that fails to fulfill the desires of those who wish to marry,

- 結婚の価値を、自分の言葉で語ることもできない、

- Not speak of the value of marriage in his own words,

そういう、無能な私(たち)に対する「痛烈な批判」である、という結論に帰着する訳です。

I can only conclude that this is a "scathing criticism" of my (our) incompetence.

2023,江端さんの忘備録

「暴力の人類史」という番組を見ました。

I watched a program called "A Human History of Violence."

題目から期待していた内容とは真逆で、「人類の暴力は減少し続けている」という内容でした。

The content was the exact opposite of what I expected from the title: "Human Violence Continues to Decrease".

しかし、私は『近代においては、戦争が、その分を喰っているんだろう』と思っていたのですが、戦争による死者数も減っているという内容でした。

But I thought, 'In modern times, war has probably replaced that,' but the number of deaths of war seems also to be decreasing.

暴力事件や戦争ニュースばかりで惑わされがちですが、数百年間のオーダーで見た時、人類は、暴力という本能を、理性という知性で押さえ続けてきた、ということです。

We are often misled by news of violent incidents and wars, but when viewed on the order of hundreds of years, humanity has continued to suppress its instinct for violence with the intelligence.

人類は、愚かな方向にのみ向いているように見えますが、案外そうでもないらしいです。

We apt to think that humanity seems to be oriented only in a foolish direction, but not so surprisingly

久々にホッする内容のドキュメンタリーでした。

It has been a long time since I was relieved by the content of this documentary.

ですが、やっぱり番組の題目は良くないと思う。

But I still think the title of the program is not proper.

-----

あ、そういえば、

―― 法律とは、「数学の証明」あるいは「システムのプログラミング」と同じである

Oh, by the way, the book mentioned here has arrived.

で記載した本が届きました。

管理システム(シビュラシステム)で守られるだけでは、人類として、ちょっと情けないですよね。

It is a bit woeful for us, as a human race, to just be protected by a management system (Sibyla system).

2023,江端さんの忘備録

日常的にChatGPTを使い倒しています。

I use ChatGPT on a daily basis.

「珍しく本当に役に立ちそうなAI技術」と認めています。

I admit "It's a rare AI technology that could be really useful".

しかし、ChatGPTは、(現時点では)『分からなくても答えを捻り出す』という悪いクセがあります(かなり見抜けるようになってきましたが)。

However, ChatGPT has a bad habit (at the moment) of "twisting answers even not knowing them" (although I'm getting pretty good at spotting them).

ですので、論文の要約などを語らせる時には、ダブルチェック用に使っています。

So I use it for double-checking when I have them talk about summaries of papers, etc.

-----

ChatGPTのアプリケーションで、私に衝撃を与えたのが、コレです(YouTubeに飛びます)

One application of ChatGPT that struck me was this one (jump to YouTube).

ChatGPTによる英会話の対話授業です。

This is an interactive class for English conversation by ChatGPT.

スマホで会話のキャッチボールをすることができて、その会話に違和感がない。

I can catch a conversation on my phone and feel comfortable with that conversation.

どっかの会社のマヌケなChatBotとは比較になりません。

It cannot be compared to some company's dumb ChatBot.

-----

私は生れて始めて『AIによる廃業』の予感を感じました ―― 最初の犠牲者は、語学教師です。

For the first time in my life, I had a premonition of "AI out of business" -- the first victims will be language teachers.

だって、英語が当たり前にしゃべれないような教師が、教育現場で英語を教えている国なんて、我が国だけですよ。

Japan is the only country in the world where teachers who do not speak English teach English in an educational setting.

AI技術のプログラムを組めない奴が、AI技術のプログラミングを語っているのと同じくらい滑稽です(ええ、はっきり言って、私は、そういうやつらを"バカ"にしているのです)。

It is as ridiculous as someone who can't program AI technology talking about programming AI technology (Well, to be clear, I am making fun of them).

上記の映像を見て頂ければ明らかですが、そんな教師より、ChatGPTの方がはるかに"マシ"です。

As the above video clearly shows, ChatGPT is much "better" than such teachers.

-----

私、以前、英語の本質は「コミュニケーション」ではなくなり、単なる「インターフェース」になるという預言をしてきました。

I, previously, have prophesied that the essence of English will cease to be "communication" and become merely an "interface".

英語が機械とのインターフェースになる日

それは、人間の内面も外面も「属性」として纏められた上で、さらにそれらの全てがスルーされて、「その人」と「私」の関係性は「価値があるか/ないか」のみの価値観で支配される世界観になる、という預言です。

Both the inside and outside of a human being are put together as "attributes" and then all of them are further passed through and the relationship between "that person" and "I" becomes a worldview governed only by the value of "is/is not worth it".

位置情報サービスからインタフェース社会へ

ところが、このChatGPTの語学教育機能は、私のこの「インタフェース世界観」を、すっかり低次元にまで落してしまったのです。

However, the language education function of ChatGPT has completely reduced this "interface worldview" of mine to a lower level.

つまり、「機械(コンピュータ)に語学を教えてもらう」ことで、「機械(コンピュータ)とコミュニケーションを行う手段」を習得することになった、ということです。

In other words, by "having a machine (computer) teach you a language," you have acquired "a means of communicating with a machine (computer).

纏めますと、『英語のコミュニケーションにおいて、「人間」が介在する意味が失われた』 ―― ということです。

It means that the significance of "human" intervention in English communication has been completely lost.

2012,江端さんの忘備録

私が、位置情報サービスの研究を行ってきたという話は、すでに何度か致しました。

この研究を進める上で、最も大変だったことは、技術開発ではありませんでした。

傲って(おごって)いると思われると嫌なのですが、詰るところ、技術というものは、金と人があれば、ある程度まではなんとかなるものなのです。

-----

位置情報サービスの研究の最大の敵は「嫌悪感」でした。

いわゆる「どこにいるか第三者に知られるのが嫌」という奴です。

「プライバシー」という言葉で良く語られてましたが、この「嫌悪感」なるやつは、まったく異なる観点から、我々の研究を技術開発を徹底的に邪魔しまくりました。

『そんな、プライバシーの侵害になるサービスが流行る訳がない』だの『人格権の侵害』だの、と、まあ色々言われて、研究の邪魔になること、まあ果てしなかったこと。

-----

私は、その度に思ったものです。

「あんたは、あんたの時間に、突然、予告もなく割り込んで、プライバシーを平気で破壊する機械 ―― 携帯電話 ―― を持ち歩いているが、それは良いのか?」

とか、

「世界中の地図を開示され、さらに自宅の外観写真まで公開されて、大騒ぎしていたのに、今は、もうどうでも良くなったのか?」

とか、

「殆どの駅に、ほぼ間断なく設置されている監視カメラは、あんたの顔を完璧に記録しているが、これは気にならないのか?」

とか。

私が不愉快に思うのは、プライバシーを標榜するくせに、その取扱に一貫性がなく、論理破綻していることです。

-----

しかし、まあ、「嫌悪感」とはそういうものだということは理解しています。

完璧に論理的であることは、人間であることを否定するようなものでしょうから。

それと、年頃に至ってない娘を持つ父親としては、娘達の位置情報は勿論、電話、メールアドレス、その他、ありとあらゆる情報が、第三者に漏洩することは、やはり心配ではあります。

とは言え、我々の存在している場所が完全に把握され、第三者に共有されることは、時間の問題だと思います。

#Facebookで、私はこれを確信しましたね(後日語ります)。

-----

では、ここで一つのテーゼを提供してみたいと思います。

世界の全ての人間の位置情報が、全て開示された世界において、何が起こるか?

私には、一つの仮説があります。

「どーでも良くなる」

-----

我々は他人の行動やプロセスには興味がなくなり、

その人の嗜好や属性も気にならなくなり、

その人と私との間におけるインターフェースだけが重要な要素になる、と。

隠されない(隠すことができなくなった)本人のプライバシーは、本人の属性としての個性と同化します。

その気の遠くなるような膨大な種類の価値観は、もはや、その人が「何を嗜好しているか」という観点を消滅させてします。

ただ、「その人」と「私」の関係性は、「価値があるか/ないか」のみの価値観で支配される世界になる、ということです。

-----

うーん、これでは良く分からないか。

では、卑近な例ではあるが、実施例を提示してみよう。

例えば、

「ゴスロリの衣装を着ている上司(男性)に、書類の決裁の印鑑を貰いに行く」

「パンクファッションをしている銀行員に、融資の相談をする」

「幼女趣味であることが分っている社長の会社に、入社する」

というイメージでしょうか。

# うーん、上手くないなぁ・・・。まだ私も整理しきれていないのです。

要するに、ありとあらゆる人間としての属性を切り捨てた、究極の「インタフェース社会」の具現化、と言えるものになるのだろう、と考えています。

2013

私は、基本的に言語以外のコミュニケーション(身振り、手振り)で、多くの国で何とかしてきました。

もちろん、ビジネスでは通用しませんが、旅行程度であれば、世界中どこでもなんとかしてみせる ―― という、漠然とした自信があります。

ですので、私は、言語に関しては「語彙」を重視する立場で、「発音」など本当にどうでもよいと思っていました。

しかし、先日のNHKのラジオ英会話番組で、私のこの考え方を根本から破壊しかねない事例が紹介されていました。

―― 英語のコミュニケーションの相手は、「人間」ではなく「機械」になる

-----

確かに、覚えがあります。

米国赴任中、電話をつかって予約をしようとしたとき、電話自動応答システムが対応してきて、色々と質問をしてきました。

『あんたは、何をしたいんだ。次の1~5の中から選べ』

と、まあ、この程度はよいのですが、

『どの空港から、どの空港へ、何日の何時の飛行機に乗りたいのか』

との、問いに対する自動音声システムは、ほぼ100%、

『ごめん。わかんない。もう一度言ってくれないかな(I am sorry, I don't understand what you said. Would you please try it again?) 』

と、の応答してくる。

で、同じ質問を三回された挙句、"Sorry, See you again" と言われて、一方的に電話を切られる。

そして、電話の受話器を持ちながら、呆然と立ちすくむ私がいる、と。

-----

相手は自動音声システムですから、身振り手振りが通じないのは当然として、聞き返し(Pardon?,Sorry?) や、「私は、あの有名な日本人なんだ(I am a Japanese, you know well)」が、通じない。

これは辛い。

これは、いわゆる私が主張してきた、「江端メソッド」を根底から破壊されかねないトレンドと言えましょう。

-----

私は、以前、寄稿コラムで、「日本の製造メーカーですら、日本語のマニュアルを作らなくなった」というお話をしました。

このような潮流が、自動音声システムにまで拡張しないと、誰が断定できるでしょうか。

コールセンタの無人化は、経費削減の観点から、絶対に止まりようがありません。これは、システムのエンジニアとして断言します。

そして、多言語対応なんぞ論外。対応言語を一元化したいと思うのは当然のことです。

TPP等によって、生保、医療、その他の分野のサービスが日本への流入してくることは確定でしょう。

日本語対応するが莫大な経費がかかる企業が勝つか、日本語対応しないが安価なサービスを提供できる企業が勝つか、今の段階では断言できません。

-----

我々には2つの道があります。

A:徹底的に英語の、特に発音に関する教育を徹底的に「破壊」して、機械とのコミュニケーションの芽を今のうちに手折る、という戦略。

B:機会とのコミュニケーションを前提に、発音を最重視する英語学習にシフトする戦略

私としては、どっちの対応も嫌です。

私の第三の戦略は、「C:このようなトレンドが、あと10年来ないことをひたすら祈り続ける」です。

2023,江端さんの技術メモ

wsl -d Ubuntu-20.04で起動しようとして、Error: 0x80040326 Error code: Wsl/Service/0x80040326 と言われた時の対応

で対応できたのは良いのですが、今度はDocker Desktopが動かなくなりました。

いわゆる、"これ"です。

error during connect: This error may indicate that the docker daemon is not running.: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/containers/json: open //./pipe/docker_engine: The system cannot find the file specified.

以下のページを参考にさせて頂きながら、色々対策していました。

https://remix-yh.net/2139/#:~:text=%E3%81%8C%E3%80%81%E5%A4%89%E6%9B%B4%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%80%82-,%E8%A7%A3%E6%B1%BA%E7%AD%96,%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82

https://engineer-ninaritai.com/docker-desktop-not-work/

などを調べていましたが、

「Docker Desktop for Windows」が起動しなくなった?

を最後の手段として腹を括ったところで、動かなかったDocker Desktopでボタン押したアップデートが突然走り出しました。

で、DBのDockerを起動して、psqlでアクセスしたらちゃんとDBが動いていることが確認できました。

こーゆーことが多いので、Docker Desktopは嫌いなんですよ。
(こんなトラブルが「顧客デモの直前」に起きたら、と思うとゾっとします)