From 9de1f9d5cc021258d72f34e8b2d866c3181c0510 Mon Sep 17 00:00:00 2001 From: Simon Let Date: Sat, 16 Apr 2022 03:56:17 +0200 Subject: [PATCH] remove packages --- pkg/histanal/histeval.go | 246 --------------------------- pkg/histanal/histload.go | 180 -------------------- pkg/strat/directory-sensitive.go | 47 ----- pkg/strat/dummy.go | 29 ---- pkg/strat/dynamic-record-distance.go | 91 ---------- pkg/strat/frequent.go | 53 ------ pkg/strat/markov-chain-cmd.go | 97 ----------- pkg/strat/markov-chain.go | 76 --------- pkg/strat/random.go | 57 ------- pkg/strat/recent-bash.go | 56 ------ pkg/strat/recent.go | 37 ---- pkg/strat/record-distance.go | 70 -------- pkg/strat/strat.go | 46 ----- 13 files changed, 1085 deletions(-) delete mode 100644 pkg/histanal/histeval.go delete mode 100644 pkg/histanal/histload.go delete mode 100644 pkg/strat/directory-sensitive.go delete mode 100644 pkg/strat/dummy.go delete mode 100644 pkg/strat/dynamic-record-distance.go delete mode 100644 pkg/strat/frequent.go delete mode 100644 pkg/strat/markov-chain-cmd.go delete mode 100644 pkg/strat/markov-chain.go delete mode 100644 pkg/strat/random.go delete mode 100644 pkg/strat/recent-bash.go delete mode 100644 pkg/strat/recent.go delete mode 100644 pkg/strat/record-distance.go delete mode 100644 pkg/strat/strat.go diff --git a/pkg/histanal/histeval.go b/pkg/histanal/histeval.go deleted file mode 100644 index 4d19779..0000000 --- a/pkg/histanal/histeval.go +++ /dev/null @@ -1,246 +0,0 @@ -package histanal - -import ( - "bytes" - "encoding/json" - "fmt" - "log" - "math/rand" - "os" - "os/exec" - - "github.com/curusarn/resh/pkg/records" - "github.com/curusarn/resh/pkg/strat" - "github.com/jpillora/longestcommon" - - "github.com/schollz/progressbar" -) - -type matchJSON struct { - Match bool - Distance int - CharsRecalled int -} - -type multiMatchItemJSON struct { - Distance int - CharsRecalled int -} - -type multiMatchJSON struct { - Match bool - Entries []multiMatchItemJSON -} - -type strategyJSON struct { - Title string - Description string - Matches []matchJSON - PrefixMatches []multiMatchJSON -} - -// HistEval evaluates history -type HistEval struct { - HistLoad - BatchMode bool - maxCandidates int - Strategies []strategyJSON -} - -// NewHistEval constructs new HistEval -func NewHistEval(inputPath string, - maxCandidates int, skipFailedCmds bool, - debugRecords float64, sanitizedInput bool) HistEval { - - e := HistEval{ - HistLoad: HistLoad{ - skipFailedCmds: skipFailedCmds, - debugRecords: debugRecords, - sanitizedInput: sanitizedInput, - }, - maxCandidates: maxCandidates, - BatchMode: false, - } - records := e.loadHistoryRecords(inputPath) - device := deviceRecords{Records: records} - user := userRecords{} - user.Devices = append(user.Devices, device) - e.UsersRecords = append(e.UsersRecords, user) - e.preprocessRecords() - return e -} - -// NewHistEvalBatchMode constructs new HistEval in batch mode -func NewHistEvalBatchMode(input string, inputDataRoot string, - maxCandidates int, skipFailedCmds bool, - debugRecords float64, sanitizedInput bool) HistEval { - - e := HistEval{ - HistLoad: HistLoad{ - skipFailedCmds: skipFailedCmds, - debugRecords: debugRecords, - sanitizedInput: sanitizedInput, - }, - maxCandidates: maxCandidates, - BatchMode: false, - } - e.UsersRecords = e.loadHistoryRecordsBatchMode(input, inputDataRoot) - e.preprocessRecords() - return e -} - -func (e *HistEval) preprocessDeviceRecords(device deviceRecords) deviceRecords { - sessionIDs := map[string]uint64{} - var nextID uint64 - nextID = 1 // start with 1 because 0 won't get saved to json - for k, record := range device.Records { - id, found := sessionIDs[record.SessionID] - if found == false { - id = nextID - sessionIDs[record.SessionID] = id - nextID++ - } - device.Records[k].SeqSessionID = id - // assert - if record.Sanitized != e.sanitizedInput { - if e.sanitizedInput { - log.Fatal("ASSERT failed: '--sanitized-input' is present but data is not sanitized") - } - log.Fatal("ASSERT failed: data is sanitized but '--sanitized-input' is not present") - } - device.Records[k].SeqSessionID = id - if e.debugRecords > 0 && rand.Float64() < e.debugRecords { - device.Records[k].DebugThisRecord = true - } - } - // sort.SliceStable(device.Records, func(x, y int) bool { - // if device.Records[x].SeqSessionID == device.Records[y].SeqSessionID { - // return device.Records[x].RealtimeAfterLocal < device.Records[y].RealtimeAfterLocal - // } - // return device.Records[x].SeqSessionID < device.Records[y].SeqSessionID - // }) - - // iterate from back and mark last record of each session - sessionIDSet := map[string]bool{} - for i := len(device.Records) - 1; i >= 0; i-- { - var record *records.EnrichedRecord - record = &device.Records[i] - if sessionIDSet[record.SessionID] { - continue - } - sessionIDSet[record.SessionID] = true - record.LastRecordOfSession = true - } - return device -} - -// enrich records and add sequential session ID -func (e *HistEval) preprocessRecords() { - for i := range e.UsersRecords { - for j := range e.UsersRecords[i].Devices { - e.UsersRecords[i].Devices[j] = e.preprocessDeviceRecords(e.UsersRecords[i].Devices[j]) - } - } -} - -// Evaluate a given strategy -func (e *HistEval) Evaluate(strategy strat.IStrategy) error { - title, description := strategy.GetTitleAndDescription() - log.Println("Evaluating strategy:", title, "-", description) - strategyData := strategyJSON{Title: title, Description: description} - for i := range e.UsersRecords { - for j := range e.UsersRecords[i].Devices { - bar := progressbar.New(len(e.UsersRecords[i].Devices[j].Records)) - var prevRecord records.EnrichedRecord - for _, record := range e.UsersRecords[i].Devices[j].Records { - if e.skipFailedCmds && record.ExitCode != 0 { - continue - } - candidates := strategy.GetCandidates(records.Stripped(record)) - if record.DebugThisRecord { - log.Println() - log.Println("===================================================") - log.Println("STRATEGY:", title, "-", description) - log.Println("===================================================") - log.Println("Previous record:") - if prevRecord.RealtimeBefore == 0 { - log.Println("== NIL") - } else { - rec, _ := prevRecord.ToString() - log.Println(rec) - } - log.Println("---------------------------------------------------") - log.Println("Recommendations for:") - rec, _ := record.ToString() - log.Println(rec) - log.Println("---------------------------------------------------") - for i, candidate := range candidates { - if i > 10 { - break - } - log.Println(string(candidate)) - } - log.Println("===================================================") - } - - matchFound := false - longestPrefixMatchLength := 0 - multiMatch := multiMatchJSON{} - for i, candidate := range candidates { - // make an option (--calculate-total) to turn this on/off ? - // if i >= e.maxCandidates { - // break - // } - commonPrefixLength := len(longestcommon.Prefix([]string{candidate, record.CmdLine})) - if commonPrefixLength > longestPrefixMatchLength { - longestPrefixMatchLength = commonPrefixLength - prefixMatch := multiMatchItemJSON{Distance: i + 1, CharsRecalled: commonPrefixLength} - multiMatch.Match = true - multiMatch.Entries = append(multiMatch.Entries, prefixMatch) - } - if candidate == record.CmdLine { - match := matchJSON{Match: true, Distance: i + 1, CharsRecalled: record.CmdLength} - matchFound = true - strategyData.Matches = append(strategyData.Matches, match) - strategyData.PrefixMatches = append(strategyData.PrefixMatches, multiMatch) - break - } - } - if matchFound == false { - strategyData.Matches = append(strategyData.Matches, matchJSON{}) - strategyData.PrefixMatches = append(strategyData.PrefixMatches, multiMatch) - } - err := strategy.AddHistoryRecord(&record) - if err != nil { - log.Println("Error while evauating", err) - return err - } - bar.Add(1) - prevRecord = record - } - strategy.ResetHistory() - fmt.Println() - } - } - e.Strategies = append(e.Strategies, strategyData) - return nil -} - -// CalculateStatsAndPlot results -func (e *HistEval) CalculateStatsAndPlot(scriptName string) { - evalJSON, err := json.Marshal(e) - if err != nil { - log.Fatal("json marshal error", err) - } - buffer := bytes.Buffer{} - buffer.Write(evalJSON) - // run python script to stat and plot/ - cmd := exec.Command(scriptName) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = &buffer - err = cmd.Run() - if err != nil { - log.Printf("Command finished with error: %v", err) - } -} diff --git a/pkg/histanal/histload.go b/pkg/histanal/histload.go deleted file mode 100644 index ec81cc2..0000000 --- a/pkg/histanal/histload.go +++ /dev/null @@ -1,180 +0,0 @@ -package histanal - -import ( - "bufio" - "encoding/json" - "fmt" - "io/ioutil" - "log" - "math/rand" - "os" - "path/filepath" - - "github.com/curusarn/resh/pkg/records" -) - -type deviceRecords struct { - Name string - Records []records.EnrichedRecord -} - -type userRecords struct { - Name string - Devices []deviceRecords -} - -// HistLoad loads history -type HistLoad struct { - UsersRecords []userRecords - skipFailedCmds bool - sanitizedInput bool - debugRecords float64 -} - -func (e *HistLoad) preprocessDeviceRecords(device deviceRecords) deviceRecords { - sessionIDs := map[string]uint64{} - var nextID uint64 - nextID = 1 // start with 1 because 0 won't get saved to json - for k, record := range device.Records { - id, found := sessionIDs[record.SessionID] - if found == false { - id = nextID - sessionIDs[record.SessionID] = id - nextID++ - } - device.Records[k].SeqSessionID = id - // assert - if record.Sanitized != e.sanitizedInput { - if e.sanitizedInput { - log.Fatal("ASSERT failed: '--sanitized-input' is present but data is not sanitized") - } - log.Fatal("ASSERT failed: data is sanitized but '--sanitized-input' is not present") - } - device.Records[k].SeqSessionID = id - if e.debugRecords > 0 && rand.Float64() < e.debugRecords { - device.Records[k].DebugThisRecord = true - } - } - // sort.SliceStable(device.Records, func(x, y int) bool { - // if device.Records[x].SeqSessionID == device.Records[y].SeqSessionID { - // return device.Records[x].RealtimeAfterLocal < device.Records[y].RealtimeAfterLocal - // } - // return device.Records[x].SeqSessionID < device.Records[y].SeqSessionID - // }) - - // iterate from back and mark last record of each session - sessionIDSet := map[string]bool{} - for i := len(device.Records) - 1; i >= 0; i-- { - var record *records.EnrichedRecord - record = &device.Records[i] - if sessionIDSet[record.SessionID] { - continue - } - sessionIDSet[record.SessionID] = true - record.LastRecordOfSession = true - } - return device -} - -// enrich records and add sequential session ID -func (e *HistLoad) preprocessRecords() { - for i := range e.UsersRecords { - for j := range e.UsersRecords[i].Devices { - e.UsersRecords[i].Devices[j] = e.preprocessDeviceRecords(e.UsersRecords[i].Devices[j]) - } - } -} - -func (e *HistLoad) loadHistoryRecordsBatchMode(fname string, dataRootPath string) []userRecords { - var records []userRecords - info, err := os.Stat(dataRootPath) - if err != nil { - log.Fatal("Error: Directory", dataRootPath, "does not exist - exiting! (", err, ")") - } - if info.IsDir() == false { - log.Fatal("Error:", dataRootPath, "is not a directory - exiting!") - } - users, err := ioutil.ReadDir(dataRootPath) - if err != nil { - log.Fatal("Could not read directory:", dataRootPath) - } - fmt.Println("Listing users in <", dataRootPath, ">...") - for _, user := range users { - userRecords := userRecords{Name: user.Name()} - userFullPath := filepath.Join(dataRootPath, user.Name()) - if user.IsDir() == false { - log.Println("Warn: Unexpected file (not a directory) <", userFullPath, "> - skipping.") - continue - } - fmt.Println() - fmt.Printf("*- %s\n", user.Name()) - devices, err := ioutil.ReadDir(userFullPath) - if err != nil { - log.Fatal("Could not read directory:", userFullPath) - } - for _, device := range devices { - deviceRecords := deviceRecords{Name: device.Name()} - deviceFullPath := filepath.Join(userFullPath, device.Name()) - if device.IsDir() == false { - log.Println("Warn: Unexpected file (not a directory) <", deviceFullPath, "> - skipping.") - continue - } - fmt.Printf(" \\- %s\n", device.Name()) - files, err := ioutil.ReadDir(deviceFullPath) - if err != nil { - log.Fatal("Could not read directory:", deviceFullPath) - } - for _, file := range files { - fileFullPath := filepath.Join(deviceFullPath, file.Name()) - if file.Name() == fname { - fmt.Printf(" \\- %s - loading ...", file.Name()) - // load the data - deviceRecords.Records = e.loadHistoryRecords(fileFullPath) - fmt.Println(" OK ✓") - } else { - fmt.Printf(" \\- %s - skipped\n", file.Name()) - } - } - userRecords.Devices = append(userRecords.Devices, deviceRecords) - } - records = append(records, userRecords) - } - return records -} - -func (e *HistLoad) loadHistoryRecords(fname string) []records.EnrichedRecord { - file, err := os.Open(fname) - if err != nil { - log.Fatal("Open() resh history file error:", err) - } - defer file.Close() - - var recs []records.EnrichedRecord - scanner := bufio.NewScanner(file) - for scanner.Scan() { - record := records.Record{} - fallbackRecord := records.FallbackRecord{} - line := scanner.Text() - err = json.Unmarshal([]byte(line), &record) - if err != nil { - err = json.Unmarshal([]byte(line), &fallbackRecord) - if err != nil { - log.Println("Line:", line) - log.Fatal("Decoding error:", err) - } - record = records.Convert(&fallbackRecord) - } - if e.sanitizedInput == false { - if record.CmdLength != 0 { - log.Fatal("Assert failed - 'cmdLength' is set in raw data. Maybe you want to use '--sanitized-input' option?") - } - record.CmdLength = len(record.CmdLine) - } else if record.CmdLength == 0 { - log.Fatal("Assert failed - 'cmdLength' is unset in the data. This should not happen.") - } - if !e.skipFailedCmds || record.ExitCode == 0 { - recs = append(recs, records.Enriched(record)) - } - } - return recs -} diff --git a/pkg/strat/directory-sensitive.go b/pkg/strat/directory-sensitive.go deleted file mode 100644 index 89d030e..0000000 --- a/pkg/strat/directory-sensitive.go +++ /dev/null @@ -1,47 +0,0 @@ -package strat - -import "github.com/curusarn/resh/pkg/records" - -// DirectorySensitive prediction/recommendation strategy -type DirectorySensitive struct { - history map[string][]string - lastPwd string -} - -// Init see name -func (s *DirectorySensitive) Init() { - s.history = map[string][]string{} -} - -// GetTitleAndDescription see name -func (s *DirectorySensitive) GetTitleAndDescription() (string, string) { - return "directory sensitive (recent)", "Use recent commands executed is the same directory" -} - -// GetCandidates see name -func (s *DirectorySensitive) GetCandidates() []string { - return s.history[s.lastPwd] -} - -// AddHistoryRecord see name -func (s *DirectorySensitive) AddHistoryRecord(record *records.EnrichedRecord) error { - // work on history for PWD - pwd := record.Pwd - // remove previous occurance of record - for i, cmd := range s.history[pwd] { - if cmd == record.CmdLine { - s.history[pwd] = append(s.history[pwd][:i], s.history[pwd][i+1:]...) - } - } - // append new record - s.history[pwd] = append([]string{record.CmdLine}, s.history[pwd]...) - s.lastPwd = record.PwdAfter - return nil -} - -// ResetHistory see name -func (s *DirectorySensitive) ResetHistory() error { - s.Init() - s.history = map[string][]string{} - return nil -} diff --git a/pkg/strat/dummy.go b/pkg/strat/dummy.go deleted file mode 100644 index fc813f2..0000000 --- a/pkg/strat/dummy.go +++ /dev/null @@ -1,29 +0,0 @@ -package strat - -import "github.com/curusarn/resh/pkg/records" - -// Dummy prediction/recommendation strategy -type Dummy struct { - history []string -} - -// GetTitleAndDescription see name -func (s *Dummy) GetTitleAndDescription() (string, string) { - return "dummy", "Return empty candidate list" -} - -// GetCandidates see name -func (s *Dummy) GetCandidates() []string { - return nil -} - -// AddHistoryRecord see name -func (s *Dummy) AddHistoryRecord(record *records.EnrichedRecord) error { - s.history = append(s.history, record.CmdLine) - return nil -} - -// ResetHistory see name -func (s *Dummy) ResetHistory() error { - return nil -} diff --git a/pkg/strat/dynamic-record-distance.go b/pkg/strat/dynamic-record-distance.go deleted file mode 100644 index 1f779c2..0000000 --- a/pkg/strat/dynamic-record-distance.go +++ /dev/null @@ -1,91 +0,0 @@ -package strat - -import ( - "math" - "sort" - "strconv" - - "github.com/curusarn/resh/pkg/records" -) - -// DynamicRecordDistance prediction/recommendation strategy -type DynamicRecordDistance struct { - history []records.EnrichedRecord - DistParams records.DistParams - pwdHistogram map[string]int - realPwdHistogram map[string]int - gitOriginHistogram map[string]int - MaxDepth int - Label string -} - -type strDynDistEntry struct { - cmdLine string - distance float64 -} - -// Init see name -func (s *DynamicRecordDistance) Init() { - s.history = nil - s.pwdHistogram = map[string]int{} - s.realPwdHistogram = map[string]int{} - s.gitOriginHistogram = map[string]int{} -} - -// GetTitleAndDescription see name -func (s *DynamicRecordDistance) GetTitleAndDescription() (string, string) { - return "dynamic record distance (depth:" + strconv.Itoa(s.MaxDepth) + ";" + s.Label + ")", "Use TF-IDF record distance to recommend commands" -} - -func (s *DynamicRecordDistance) idf(count int) float64 { - return math.Log(float64(len(s.history)) / float64(count)) -} - -// GetCandidates see name -func (s *DynamicRecordDistance) GetCandidates(strippedRecord records.EnrichedRecord) []string { - if len(s.history) == 0 { - return nil - } - var mapItems []strDynDistEntry - for i, record := range s.history { - if s.MaxDepth != 0 && i > s.MaxDepth { - break - } - distParams := records.DistParams{ - Pwd: s.DistParams.Pwd * s.idf(s.pwdHistogram[strippedRecord.PwdAfter]), - RealPwd: s.DistParams.RealPwd * s.idf(s.realPwdHistogram[strippedRecord.RealPwdAfter]), - Git: s.DistParams.Git * s.idf(s.gitOriginHistogram[strippedRecord.GitOriginRemote]), - Time: s.DistParams.Time, - SessionID: s.DistParams.SessionID, - } - distance := record.DistanceTo(strippedRecord, distParams) - mapItems = append(mapItems, strDynDistEntry{record.CmdLine, distance}) - } - sort.SliceStable(mapItems, func(i int, j int) bool { return mapItems[i].distance < mapItems[j].distance }) - var hist []string - histSet := map[string]bool{} - for _, item := range mapItems { - if histSet[item.cmdLine] { - continue - } - histSet[item.cmdLine] = true - hist = append(hist, item.cmdLine) - } - return hist -} - -// AddHistoryRecord see name -func (s *DynamicRecordDistance) AddHistoryRecord(record *records.EnrichedRecord) error { - // append record to front - s.history = append([]records.EnrichedRecord{*record}, s.history...) - s.pwdHistogram[record.Pwd]++ - s.realPwdHistogram[record.RealPwd]++ - s.gitOriginHistogram[record.GitOriginRemote]++ - return nil -} - -// ResetHistory see name -func (s *DynamicRecordDistance) ResetHistory() error { - s.Init() - return nil -} diff --git a/pkg/strat/frequent.go b/pkg/strat/frequent.go deleted file mode 100644 index ff3b912..0000000 --- a/pkg/strat/frequent.go +++ /dev/null @@ -1,53 +0,0 @@ -package strat - -import ( - "sort" - - "github.com/curusarn/resh/pkg/records" -) - -// Frequent prediction/recommendation strategy -type Frequent struct { - history map[string]int -} - -type strFrqEntry struct { - cmdLine string - count int -} - -// Init see name -func (s *Frequent) Init() { - s.history = map[string]int{} -} - -// GetTitleAndDescription see name -func (s *Frequent) GetTitleAndDescription() (string, string) { - return "frequent", "Use frequent commands" -} - -// GetCandidates see name -func (s *Frequent) GetCandidates() []string { - var mapItems []strFrqEntry - for cmdLine, count := range s.history { - mapItems = append(mapItems, strFrqEntry{cmdLine, count}) - } - sort.Slice(mapItems, func(i int, j int) bool { return mapItems[i].count > mapItems[j].count }) - var hist []string - for _, item := range mapItems { - hist = append(hist, item.cmdLine) - } - return hist -} - -// AddHistoryRecord see name -func (s *Frequent) AddHistoryRecord(record *records.EnrichedRecord) error { - s.history[record.CmdLine]++ - return nil -} - -// ResetHistory see name -func (s *Frequent) ResetHistory() error { - s.Init() - return nil -} diff --git a/pkg/strat/markov-chain-cmd.go b/pkg/strat/markov-chain-cmd.go deleted file mode 100644 index b1fa2f5..0000000 --- a/pkg/strat/markov-chain-cmd.go +++ /dev/null @@ -1,97 +0,0 @@ -package strat - -import ( - "sort" - "strconv" - - "github.com/curusarn/resh/pkg/records" - "github.com/mb-14/gomarkov" -) - -// MarkovChainCmd prediction/recommendation strategy -type MarkovChainCmd struct { - Order int - history []strMarkCmdHistoryEntry - historyCmds []string -} - -type strMarkCmdHistoryEntry struct { - cmd string - cmdLine string -} - -type strMarkCmdEntry struct { - cmd string - transProb float64 -} - -// Init see name -func (s *MarkovChainCmd) Init() { - s.history = nil - s.historyCmds = nil -} - -// GetTitleAndDescription see name -func (s *MarkovChainCmd) GetTitleAndDescription() (string, string) { - return "command-based markov chain (order " + strconv.Itoa(s.Order) + ")", "Use command-based markov chain to recommend commands" -} - -// GetCandidates see name -func (s *MarkovChainCmd) 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 -} - -// AddHistoryRecord see name -func (s *MarkovChainCmd) AddHistoryRecord(record *records.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 -} - -// ResetHistory see name -func (s *MarkovChainCmd) ResetHistory() error { - s.Init() - return nil -} diff --git a/pkg/strat/markov-chain.go b/pkg/strat/markov-chain.go deleted file mode 100644 index 50c7fdc..0000000 --- a/pkg/strat/markov-chain.go +++ /dev/null @@ -1,76 +0,0 @@ -package strat - -import ( - "sort" - "strconv" - - "github.com/curusarn/resh/pkg/records" - "github.com/mb-14/gomarkov" -) - -// MarkovChain prediction/recommendation strategy -type MarkovChain struct { - Order int - history []string -} - -type strMarkEntry struct { - cmdLine string - transProb float64 -} - -// Init see name -func (s *MarkovChain) Init() { - s.history = nil -} - -// GetTitleAndDescription see name -func (s *MarkovChain) GetTitleAndDescription() (string, string) { - return "markov chain (order " + strconv.Itoa(s.Order) + ")", "Use markov chain to recommend commands" -} - -// GetCandidates see name -func (s *MarkovChain) 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 -} - -// AddHistoryRecord see name -func (s *MarkovChain) AddHistoryRecord(record *records.EnrichedRecord) error { - s.history = append(s.history, record.CmdLine) - // s.historySet[record.CmdLine] = true - return nil -} - -// ResetHistory see name -func (s *MarkovChain) ResetHistory() error { - s.Init() - return nil -} diff --git a/pkg/strat/random.go b/pkg/strat/random.go deleted file mode 100644 index 0ff52f1..0000000 --- a/pkg/strat/random.go +++ /dev/null @@ -1,57 +0,0 @@ -package strat - -import ( - "math/rand" - "time" - - "github.com/curusarn/resh/pkg/records" -) - -// Random prediction/recommendation strategy -type Random struct { - CandidatesSize int - history []string - historySet map[string]bool -} - -// Init see name -func (s *Random) Init() { - s.history = nil - s.historySet = map[string]bool{} -} - -// GetTitleAndDescription see name -func (s *Random) GetTitleAndDescription() (string, string) { - return "random", "Use random commands" -} - -// GetCandidates see name -func (s *Random) 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 -} - -// AddHistoryRecord see name -func (s *Random) AddHistoryRecord(record *records.EnrichedRecord) error { - s.history = append([]string{record.CmdLine}, s.history...) - s.historySet[record.CmdLine] = true - return nil -} - -// ResetHistory see name -func (s *Random) ResetHistory() error { - s.Init() - return nil -} diff --git a/pkg/strat/recent-bash.go b/pkg/strat/recent-bash.go deleted file mode 100644 index ace3571..0000000 --- a/pkg/strat/recent-bash.go +++ /dev/null @@ -1,56 +0,0 @@ -package strat - -import "github.com/curusarn/resh/pkg/records" - -// RecentBash prediction/recommendation strategy -type RecentBash struct { - histfile []string - histfileSnapshot map[string][]string - history map[string][]string -} - -// Init see name -func (s *RecentBash) Init() { - s.histfileSnapshot = map[string][]string{} - s.history = map[string][]string{} -} - -// GetTitleAndDescription see name -func (s *RecentBash) GetTitleAndDescription() (string, string) { - return "recent (bash-like)", "Behave like bash" -} - -// GetCandidates see name -func (s *RecentBash) GetCandidates(strippedRecord records.EnrichedRecord) []string { - // populate the local history from histfile - if s.histfileSnapshot[strippedRecord.SessionID] == nil { - s.histfileSnapshot[strippedRecord.SessionID] = s.histfile - } - return append(s.history[strippedRecord.SessionID], s.histfileSnapshot[strippedRecord.SessionID]...) -} - -// AddHistoryRecord see name -func (s *RecentBash) AddHistoryRecord(record *records.EnrichedRecord) error { - // remove previous occurance of record - for i, cmd := range s.history[record.SessionID] { - if cmd == record.CmdLine { - s.history[record.SessionID] = append(s.history[record.SessionID][:i], s.history[record.SessionID][i+1:]...) - } - } - // append new record - s.history[record.SessionID] = append([]string{record.CmdLine}, s.history[record.SessionID]...) - - if record.LastRecordOfSession { - // append history of the session to histfile and clear session history - s.histfile = append(s.history[record.SessionID], s.histfile...) - s.histfileSnapshot[record.SessionID] = nil - s.history[record.SessionID] = nil - } - return nil -} - -// ResetHistory see name -func (s *RecentBash) ResetHistory() error { - s.Init() - return nil -} diff --git a/pkg/strat/recent.go b/pkg/strat/recent.go deleted file mode 100644 index 157b52c..0000000 --- a/pkg/strat/recent.go +++ /dev/null @@ -1,37 +0,0 @@ -package strat - -import "github.com/curusarn/resh/pkg/records" - -// Recent prediction/recommendation strategy -type Recent struct { - history []string -} - -// GetTitleAndDescription see name -func (s *Recent) GetTitleAndDescription() (string, string) { - return "recent", "Use recent commands" -} - -// GetCandidates see name -func (s *Recent) GetCandidates() []string { - return s.history -} - -// AddHistoryRecord see name -func (s *Recent) AddHistoryRecord(record *records.EnrichedRecord) error { - // remove previous occurance of record - for i, cmd := range s.history { - if cmd == record.CmdLine { - s.history = append(s.history[:i], s.history[i+1:]...) - } - } - // append new record - s.history = append([]string{record.CmdLine}, s.history...) - return nil -} - -// ResetHistory see name -func (s *Recent) ResetHistory() error { - s.history = nil - return nil -} diff --git a/pkg/strat/record-distance.go b/pkg/strat/record-distance.go deleted file mode 100644 index e582584..0000000 --- a/pkg/strat/record-distance.go +++ /dev/null @@ -1,70 +0,0 @@ -package strat - -import ( - "sort" - "strconv" - - "github.com/curusarn/resh/pkg/records" -) - -// RecordDistance prediction/recommendation strategy -type RecordDistance struct { - history []records.EnrichedRecord - DistParams records.DistParams - MaxDepth int - Label string -} - -type strDistEntry struct { - cmdLine string - distance float64 -} - -// Init see name -func (s *RecordDistance) Init() { - s.history = nil -} - -// GetTitleAndDescription see name -func (s *RecordDistance) GetTitleAndDescription() (string, string) { - return "record distance (depth:" + strconv.Itoa(s.MaxDepth) + ";" + s.Label + ")", "Use record distance to recommend commands" -} - -// GetCandidates see name -func (s *RecordDistance) GetCandidates(strippedRecord records.EnrichedRecord) []string { - if len(s.history) == 0 { - return nil - } - var mapItems []strDistEntry - for i, record := range s.history { - if s.MaxDepth != 0 && i > s.MaxDepth { - break - } - distance := record.DistanceTo(strippedRecord, s.DistParams) - mapItems = append(mapItems, strDistEntry{record.CmdLine, distance}) - } - sort.SliceStable(mapItems, func(i int, j int) bool { return mapItems[i].distance < mapItems[j].distance }) - var hist []string - histSet := map[string]bool{} - for _, item := range mapItems { - if histSet[item.cmdLine] { - continue - } - histSet[item.cmdLine] = true - hist = append(hist, item.cmdLine) - } - return hist -} - -// AddHistoryRecord see name -func (s *RecordDistance) AddHistoryRecord(record *records.EnrichedRecord) error { - // append record to front - s.history = append([]records.EnrichedRecord{*record}, s.history...) - return nil -} - -// ResetHistory see name -func (s *RecordDistance) ResetHistory() error { - s.Init() - return nil -} diff --git a/pkg/strat/strat.go b/pkg/strat/strat.go deleted file mode 100644 index 28ac015..0000000 --- a/pkg/strat/strat.go +++ /dev/null @@ -1,46 +0,0 @@ -package strat - -import ( - "github.com/curusarn/resh/pkg/records" -) - -// ISimpleStrategy interface -type ISimpleStrategy interface { - GetTitleAndDescription() (string, string) - GetCandidates() []string - AddHistoryRecord(record *records.EnrichedRecord) error - ResetHistory() error -} - -// IStrategy interface -type IStrategy interface { - GetTitleAndDescription() (string, string) - GetCandidates(r records.EnrichedRecord) []string - AddHistoryRecord(record *records.EnrichedRecord) error - ResetHistory() error -} - -type simpleStrategyWrapper struct { - strategy ISimpleStrategy -} - -// NewSimpleStrategyWrapper returns IStrategy created by wrapping given ISimpleStrategy -func NewSimpleStrategyWrapper(strategy ISimpleStrategy) *simpleStrategyWrapper { - return &simpleStrategyWrapper{strategy: strategy} -} - -func (s *simpleStrategyWrapper) GetTitleAndDescription() (string, string) { - return s.strategy.GetTitleAndDescription() -} - -func (s *simpleStrategyWrapper) GetCandidates(r records.EnrichedRecord) []string { - return s.strategy.GetCandidates() -} - -func (s *simpleStrategyWrapper) AddHistoryRecord(r *records.EnrichedRecord) error { - return s.strategy.AddHistoryRecord(r) -} - -func (s *simpleStrategyWrapper) ResetHistory() error { - return s.strategy.ResetHistory() -}