mirror of https://github.com/curusarn/resh
enrich: add 'command' on top of 'firstWord' - first word is not always command strategies: add 'random' strategy, add markov chain based strategies evaluate: add plot with average recalled characters including prefix matchespull/15/head
parent
1bc5ef53f1
commit
ff878a9d79
@ -0,0 +1,91 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"sort" |
||||
"strconv" |
||||
|
||||
"github.com/curusarn/resh/common" |
||||
"github.com/mb-14/gomarkov" |
||||
) |
||||
|
||||
type strategyMarkovChainCmd struct { |
||||
order int |
||||
history []strMarkCmdHistoryEntry |
||||
historyCmds []string |
||||
} |
||||
|
||||
type strMarkCmdHistoryEntry struct { |
||||
cmd string |
||||
cmdLine string |
||||
} |
||||
|
||||
type strMarkCmdEntry struct { |
||||
cmd string |
||||
transProb float64 |
||||
} |
||||
|
||||
func (s *strategyMarkovChainCmd) init() { |
||||
s.history = nil |
||||
s.historyCmds = nil |
||||
} |
||||
|
||||
func (s *strategyMarkovChainCmd) GetTitleAndDescription() (string, string) { |
||||
return "command-based markov chain (order " + strconv.Itoa(s.order) + ")", "Use command-based markov chain to recommend commands" |
||||
} |
||||
|
||||
func (s *strategyMarkovChainCmd) GetCandidates() []string { |
||||
if len(s.history) < s.order { |
||||
var hist []string |
||||
for _, item := range s.history { |
||||
hist = append(hist, item.cmdLine) |
||||
} |
||||
return hist |
||||
} |
||||
chain := gomarkov.NewChain(s.order) |
||||
|
||||
chain.Add(s.historyCmds) |
||||
|
||||
cmdsSet := map[string]bool{} |
||||
var entries []strMarkCmdEntry |
||||
for _, cmd := range s.historyCmds { |
||||
if cmdsSet[cmd] { |
||||
continue |
||||
} |
||||
cmdsSet[cmd] = true |
||||
prob, _ := chain.TransitionProbability(cmd, s.historyCmds[len(s.historyCmds)-s.order:]) |
||||
entries = append(entries, strMarkCmdEntry{cmd: cmd, transProb: prob}) |
||||
} |
||||
sort.Slice(entries, func(i int, j int) bool { return entries[i].transProb > entries[j].transProb }) |
||||
var hist []string |
||||
histSet := map[string]bool{} |
||||
for i := len(s.history) - 1; i >= 0; i-- { |
||||
if histSet[s.history[i].cmdLine] { |
||||
continue |
||||
} |
||||
histSet[s.history[i].cmdLine] = true |
||||
if s.history[i].cmd == entries[0].cmd { |
||||
hist = append(hist, s.history[i].cmdLine) |
||||
} |
||||
} |
||||
// log.Println("################")
|
||||
// log.Println(s.history[len(s.history)-s.order:])
|
||||
// log.Println(" -> ")
|
||||
// x := math.Min(float64(len(hist)), 3)
|
||||
// log.Println(entries[:int(x)])
|
||||
// x = math.Min(float64(len(hist)), 5)
|
||||
// log.Println(hist[:int(x)])
|
||||
// log.Println("################")
|
||||
return hist |
||||
} |
||||
|
||||
func (s *strategyMarkovChainCmd) AddHistoryRecord(record *common.EnrichedRecord) error { |
||||
s.history = append(s.history, strMarkCmdHistoryEntry{cmdLine: record.CmdLine, cmd: record.Command}) |
||||
s.historyCmds = append(s.historyCmds, record.Command) |
||||
// s.historySet[record.CmdLine] = true
|
||||
return nil |
||||
} |
||||
|
||||
func (s *strategyMarkovChainCmd) ResetHistory() error { |
||||
s.init() |
||||
return nil |
||||
} |
||||
@ -0,0 +1,70 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"sort" |
||||
"strconv" |
||||
|
||||
"github.com/curusarn/resh/common" |
||||
"github.com/mb-14/gomarkov" |
||||
) |
||||
|
||||
type strategyMarkovChain struct { |
||||
order int |
||||
history []string |
||||
} |
||||
|
||||
type strMarkEntry struct { |
||||
cmdLine string |
||||
transProb float64 |
||||
} |
||||
|
||||
func (s *strategyMarkovChain) init() { |
||||
s.history = nil |
||||
} |
||||
|
||||
func (s *strategyMarkovChain) GetTitleAndDescription() (string, string) { |
||||
return "markov chain (order " + strconv.Itoa(s.order) + ")", "Use markov chain to recommend commands" |
||||
} |
||||
|
||||
func (s *strategyMarkovChain) GetCandidates() []string { |
||||
if len(s.history) < s.order { |
||||
return s.history |
||||
} |
||||
chain := gomarkov.NewChain(s.order) |
||||
|
||||
chain.Add(s.history) |
||||
|
||||
cmdLinesSet := map[string]bool{} |
||||
var entries []strMarkEntry |
||||
for _, cmdLine := range s.history { |
||||
if cmdLinesSet[cmdLine] { |
||||
continue |
||||
} |
||||
cmdLinesSet[cmdLine] = true |
||||
prob, _ := chain.TransitionProbability(cmdLine, s.history[len(s.history)-s.order:]) |
||||
entries = append(entries, strMarkEntry{cmdLine: cmdLine, transProb: prob}) |
||||
} |
||||
sort.Slice(entries, func(i int, j int) bool { return entries[i].transProb > entries[j].transProb }) |
||||
var hist []string |
||||
for _, item := range entries { |
||||
hist = append(hist, item.cmdLine) |
||||
} |
||||
// log.Println("################")
|
||||
// log.Println(s.history[len(s.history)-s.order:])
|
||||
// log.Println(" -> ")
|
||||
// x := math.Min(float64(len(hist)), 5)
|
||||
// log.Println(hist[:int(x)])
|
||||
// log.Println("################")
|
||||
return hist |
||||
} |
||||
|
||||
func (s *strategyMarkovChain) AddHistoryRecord(record *common.EnrichedRecord) error { |
||||
s.history = append(s.history, record.CmdLine) |
||||
// s.historySet[record.CmdLine] = true
|
||||
return nil |
||||
} |
||||
|
||||
func (s *strategyMarkovChain) ResetHistory() error { |
||||
s.init() |
||||
return nil |
||||
} |
||||
@ -0,0 +1,51 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"math/rand" |
||||
"time" |
||||
|
||||
"github.com/curusarn/resh/common" |
||||
) |
||||
|
||||
type strategyRandom struct { |
||||
candidatesSize int |
||||
history []string |
||||
historySet map[string]bool |
||||
} |
||||
|
||||
func (s *strategyRandom) init() { |
||||
s.history = nil |
||||
s.historySet = map[string]bool{} |
||||
} |
||||
|
||||
func (s *strategyRandom) GetTitleAndDescription() (string, string) { |
||||
return "random", "Use random commands" |
||||
} |
||||
|
||||
func (s *strategyRandom) GetCandidates() []string { |
||||
seed := time.Now().UnixNano() |
||||
rand.Seed(seed) |
||||
var candidates []string |
||||
candidateSet := map[string]bool{} |
||||
for len(candidates) < s.candidatesSize && len(candidates)*2 < len(s.historySet) { |
||||
x := rand.Intn(len(s.history)) |
||||
candidate := s.history[x] |
||||
if candidateSet[candidate] == false { |
||||
candidateSet[candidate] = true |
||||
candidates = append(candidates, candidate) |
||||
continue |
||||
} |
||||
} |
||||
return candidates |
||||
} |
||||
|
||||
func (s *strategyRandom) AddHistoryRecord(record *common.EnrichedRecord) error { |
||||
s.history = append([]string{record.CmdLine}, s.history...) |
||||
s.historySet[record.CmdLine] = true |
||||
return nil |
||||
} |
||||
|
||||
func (s *strategyRandom) ResetHistory() error { |
||||
s.init() |
||||
return nil |
||||
} |
||||
Loading…
Reference in new issue