Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

treat message by pointer #38

Merged
merged 1 commit into from
May 7, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions scripts/lib/generator.go
Original file line number Diff line number Diff line change
@@ -122,14 +122,9 @@ func (g *HTMLGenerator) generateChannelDir(path string, channel Channel) (bool,
return false, fmt.Errorf("could not create %s directory: %w", path, err)
}

keys := make([]MessageMonthKey, 0, len(msgsMap))
for key := range msgsMap {
keys = append(keys, key)
}
Comment on lines -125 to -128
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MessageMap.Keys() へ移動した。


if err := g.generateChannelIndex(
channel,
keys,
msgsMap.Keys(),
filepath.Join(path, "index.html"),
); err != nil {
return true, err
@@ -178,7 +173,7 @@ func (g *HTMLGenerator) generateChannelIndex(channel Channel, keys []MessageMont
return nil
}

func (g *HTMLGenerator) generateMessageDir(channel Channel, key MessageMonthKey, msgs []Message, path string) error {
func (g *HTMLGenerator) generateMessageDir(channel Channel, key MessageMonthKey, msgs Messages, path string) error {
if err := os.MkdirAll(path, 0777); err != nil {
return fmt.Errorf("could not create %s directory: %w", path, err)
}
@@ -233,7 +228,7 @@ func (g *HTMLGenerator) generateMessageDir(channel Channel, key MessageMonthKey,
}
return ""
},
"threads": func(ts string) []Message {
"threads": func(ts string) Messages {
if t, ok := g.s.GetThread(channel.ID, ts); ok {
return t.Replies()
}
68 changes: 40 additions & 28 deletions scripts/lib/message.go
Original file line number Diff line number Diff line change
@@ -11,6 +11,29 @@ import (
"strings"
)

// Messages is an array of `*Message`.
type Messages []*Message

// Sort sorts messages by `Message.Ts` ascendant order.
func (msgs Messages) Sort() {
sort.SliceStable(msgs, func(i, j int) bool {
// must be the same digits, so no need to convert the timestamp to a number
return msgs[i].Ts < msgs[j].Ts
})
}

// MessagesMap is a map, maps MessageMonthKey to Messages.
type MessagesMap map[MessageMonthKey]Messages

// Keys returns all keys in the map.
func (mm MessagesMap) Keys() []MessageMonthKey {
keys := make([]MessageMonthKey, 0, len(mm))
for key := range mm {
keys = append(keys, key)
}
return keys
}

// MessageTable : メッセージデータを保持する
// スレッドは投稿時刻からどのスレッドへの返信かが判断できるためThreadMapのキー
// はtsである。
@@ -20,7 +43,7 @@ import (
type MessageTable struct {
// key: thread timestamp
ThreadMap map[string]*Thread
MsgsMap map[MessageMonthKey][]Message
MsgsMap MessagesMap
// key: file path
loadedFiles map[string]struct{}
}
@@ -32,7 +55,7 @@ type MessageTable struct {
func NewMessageTable() *MessageTable {
return &MessageTable{
ThreadMap: map[string]*Thread{},
MsgsMap: map[MessageMonthKey][]Message{},
MsgsMap: MessagesMap{},
loadedFiles: map[string]struct{}{},
}
}
@@ -79,13 +102,15 @@ func (m *MessageTable) ReadLogFile(path string) error {
return nil
}

var msgs []Message
var visibleMsgs []Message
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

少し後ろの、本当に必要になる直前で宣言するように移動した。

var msgs Messages
err = ReadFileAsJSON(path, &msgs)
if err != nil {
return fmt.Errorf("failed to unmarshal %s: %w", path, err)
}
for i, msg := range msgs {

// assort messages, visible and threaded.
var visibleMsgs Messages
for _, msg := range msgs {
if !msg.IsVisible() {
continue
}
@@ -97,18 +122,12 @@ func (m *MessageTable) ReadLogFile(path string) error {
visibleMsgs = append(visibleMsgs, msg)
}
if threadTs != "" {
if m.ThreadMap[threadTs] == nil {
m.ThreadMap[threadTs] = &Thread{}
}
if msg.IsRootOfThread() {
m.ThreadMap[threadTs].rootMsg = &msgs[i]
} else {
if m.ThreadMap[threadTs].replies == nil {
m.ThreadMap[threadTs].replies = []Message{msg}
} else {
m.ThreadMap[threadTs].replies = append(m.ThreadMap[threadTs].replies, msg)
}
thread, ok := m.ThreadMap[threadTs]
if !ok {
thread = &Thread{}
m.ThreadMap[threadTs] = thread
}
thread.Put(msg)
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mapの値がポインタならば以下の3ステップで書くのが見通しが良くなるコツ。
ここはその形式に直した。

  1. ローカル変数へ取り出してみる
  2. なければ空のを突っ込むローカル変数とmapに突っ込む
  3. ローカル変数のを加工する

}

@@ -117,22 +136,15 @@ func (m *MessageTable) ReadLogFile(path string) error {
return err
}
if len(visibleMsgs) != 0 {
if _, ok := m.MsgsMap[key]; !ok {
m.MsgsMap[key] = visibleMsgs
} else {
m.MsgsMap[key] = append(m.MsgsMap[key], visibleMsgs...)
}
Comment on lines -120 to -124
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここは上記のスライス版。

  • 存在しないkeyにmapはゼロ値を返す
  • スライスのゼロ値はnil
  • nil スライスは append() の第1引数に渡せる&適切にアロケーションしてくれる

のコンボでこうなる。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あー、nil スライス append に渡せないと勘違いしてました

m.MsgsMap[key] = append(m.MsgsMap[key], visibleMsgs...)
}

for key, msgs := range m.MsgsMap {
sort.SliceStable(m.MsgsMap[key], func(i, j int) bool {
// must be the same digits, so no need to convert the timestamp to a number
return m.MsgsMap[key][i].Ts < m.MsgsMap[key][j].Ts
})
Comment on lines -128 to -131
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Messages.Sort() として切り出した。

for _, msgs := range m.MsgsMap {
msgs.Sort()
var lastUser string
for i, msg := range msgs {
for _, msg := range msgs {
if lastUser == msg.User {
(&msgs[i]).Trail = true
msg.Trail = true
} else {
lastUser = msg.User
}
2 changes: 1 addition & 1 deletion scripts/lib/store.go
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ func (s *LogStore) HasPrevMonth(channelID string, key MessageMonthKey) bool {
return false
}

func (s *LogStore) GetMessagesPerMonth(channelID string) (map[MessageMonthKey][]Message, error) {
func (s *LogStore) GetMessagesPerMonth(channelID string) (MessagesMap, error) {
mt, ok := s.mts[channelID]
if !ok {
return nil, fmt.Errorf("not found channel: id=%s", channelID)
27 changes: 18 additions & 9 deletions scripts/lib/thread.go
Original file line number Diff line number Diff line change
@@ -9,21 +9,30 @@ import (
// repliesにはそのスレッドへの返信メッセージが入る。先頭メッセージは含まない。
type Thread struct {
rootMsg *Message
replies []Message
replies Messages
}

func (t Thread) LastReplyTime() time.Time {
Copy link
Member Author

@koron koron May 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

以下レシーバーの名前を t から th へ変更。

テストを書くと t *testing.T となるので Thread のレシーバーとしては t は使えずぐんにょりするのを今のうちに回避した。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// 丁度別件で踏みました...

return TsToDateTime(t.replies[len(t.replies)-1].Ts)
func (th Thread) LastReplyTime() time.Time {
return TsToDateTime(th.replies[len(th.replies)-1].Ts)
}

func (t Thread) ReplyCount() int {
return len(t.replies)
func (th Thread) ReplyCount() int {
return len(th.replies)
}

func (t Thread) RootText() string {
return t.rootMsg.Text
func (th Thread) RootText() string {
return th.rootMsg.Text
}

func (t Thread) Replies() []Message {
return t.replies
func (th Thread) Replies() Messages {
return th.replies
}

// Put puts a message to the thread as "root" or "reply".
func (th *Thread) Put(m *Message) {
if m.IsRootOfThread() {
th.rootMsg = m
} else {
th.replies = append(th.replies, m)
}
}