add strategies: frequent, directory sensitive; sort records by session and time

pull/13/head
Simon Let 6 years ago
parent 367263b28c
commit 67ab2ffaef
  1. 5
      common/resh-common.go
  2. 62
      evaluate/resh-evaluate-plot.py
  3. 26
      evaluate/resh-evaluate.go
  4. 42
      evaluate/strategy-directory-sensitive.go
  5. 47
      evaluate/strategy-frequent.go
  6. 1
      evaluate/strategy-recent.go

@ -74,8 +74,9 @@ type Record struct {
CmdLength int `json:"cmdLength"` CmdLength int `json:"cmdLength"`
// enriching fields - added "later" // enriching fields - added "later"
FirstWord string `json:"firstWord"` FirstWord string `json:"firstWord"`
Invalid bool `json:"invalid"` Invalid bool `json:"invalid"`
SeqSessionID uint64 `json:"seqSessionID"`
} }
// FallbackRecord when record is too old and can't be parsed into regular Record // FallbackRecord when record is too old and can't be parsed into regular Record

@ -26,7 +26,7 @@ for user in data["UsersRecords"]:
continue continue
DATA_records.append(record) DATA_records.append(record)
DATA_records_by_session[record["sessionPid"]].append(record) DATA_records_by_session[record["sessionId"]].append(record)
DATA_records = list(sorted(DATA_records, key=lambda x: x["realtimeBeforeLocal"])) DATA_records = list(sorted(DATA_records, key=lambda x: x["realtimeBeforeLocal"]))
@ -265,6 +265,9 @@ def plot_strategies_matches(plot_size=50, selected_strategies=[]):
plt.ylabel('%' + " of matches") plt.ylabel('%' + " of matches")
plt.xlabel("Distance") plt.xlabel("Distance")
legend = [] legend = []
x_values = range(1, plot_size+1)
saved_matches_total = None
saved_dataPoint_count = None
for strategy in data["Strategies"]: for strategy in data["Strategies"]:
strategy_title = strategy["Title"] strategy_title = strategy["Title"]
# strategy_description = strategy["Description"] # strategy_description = strategy["Description"]
@ -295,24 +298,34 @@ def plot_strategies_matches(plot_size=50, selected_strategies=[]):
matches[dist-1] += 1 matches[dist-1] += 1
charsRecalled[dist-1] += chars charsRecalled[dist-1] += chars
# recent is very simple strategy so we will believe
# that there is no bug in it and we can use it to determine total
if strategy_title == "recent":
saved_matches_total = matches_total
saved_dataPoint_count = dataPoint_count
if len(selected_strategies) and strategy_title not in selected_strategies:
continue
acc = 0 acc = 0
matches_cumulative = [] matches_cumulative = []
for x in matches: for x in matches:
acc += x acc += x
matches_cumulative.append(acc) matches_cumulative.append(acc)
matches_cumulative.append(matches_total) # matches_cumulative.append(matches_total)
matches_percent = list(map(lambda x: 100 * x / dataPoint_count, matches_cumulative)) matches_percent = list(map(lambda x: 100 * x / dataPoint_count, matches_cumulative))
x_values = range(1, plot_size+2)
plt.plot(x_values, matches_percent, 'o-') plt.plot(x_values, matches_percent, 'o-')
legend.append(strategy_title) legend.append(strategy_title)
assert(saved_matches_total is not None)
assert(saved_dataPoint_count is not None)
max_values = [100 * saved_matches_total / saved_dataPoint_count] * len(x_values)
plt.plot(x_values, max_values, 'r-')
legend.append("maximum possible")
x_ticks = list(range(1, plot_size+1, 2)) x_ticks = list(range(1, plot_size+1, 2))
x_labels = x_ticks[:] x_labels = x_ticks[:]
x_ticks.append(plot_size+1)
x_labels.append("total")
plt.xticks(x_ticks, x_labels) plt.xticks(x_ticks, x_labels)
plt.legend(legend, loc="best") plt.legend(legend, loc="best")
plt.show() plt.show()
@ -324,14 +337,14 @@ def plot_strategies_charsRecalled(plot_size=50, selected_strategies=[]):
plt.title("Average characters recalled at distance") plt.title("Average characters recalled at distance")
plt.ylabel("Average characters recalled") plt.ylabel("Average characters recalled")
plt.xlabel("Distance") plt.xlabel("Distance")
x_values = range(1, plot_size+1)
legend = [] legend = []
saved_charsRecalled_total = None
saved_dataPoint_count = None
for strategy in data["Strategies"]: for strategy in data["Strategies"]:
strategy_title = strategy["Title"] strategy_title = strategy["Title"]
# strategy_description = strategy["Description"] # strategy_description = strategy["Description"]
if len(selected_strategies) and strategy_title not in selected_strategies:
continue
dataPoint_count = 0 dataPoint_count = 0
matches = [0] * plot_size matches = [0] * plot_size
matches_total = 0 matches_total = 0
@ -355,38 +368,47 @@ def plot_strategies_charsRecalled(plot_size=50, selected_strategies=[]):
matches[dist-1] += 1 matches[dist-1] += 1
charsRecalled[dist-1] += chars charsRecalled[dist-1] += chars
# recent is very simple strategy so we will believe
# that there is no bug in it and we can use it to determine total
if strategy_title == "recent":
saved_charsRecalled_total = charsRecalled_total
saved_dataPoint_count = dataPoint_count
if len(selected_strategies) and strategy_title not in selected_strategies:
continue
acc = 0 acc = 0
charsRecalled_cumulative = [] charsRecalled_cumulative = []
for x in charsRecalled: for x in charsRecalled:
acc += x acc += x
charsRecalled_cumulative.append(acc) charsRecalled_cumulative.append(acc)
charsRecalled_cumulative.append(charsRecalled_total)
charsRecalled_average = list(map(lambda x: x / dataPoint_count, charsRecalled_cumulative)) charsRecalled_average = list(map(lambda x: x / dataPoint_count, charsRecalled_cumulative))
x_values = range(1, plot_size+2)
plt.plot(x_values, charsRecalled_average, 'o-') plt.plot(x_values, charsRecalled_average, 'o-')
legend.append(strategy_title) legend.append(strategy_title)
assert(saved_charsRecalled_total is not None)
assert(saved_dataPoint_count is not None)
max_values = [saved_charsRecalled_total / saved_dataPoint_count] * len(x_values)
plt.plot(x_values, max_values, 'r-')
legend.append("maximum possible")
x_ticks = list(range(1, plot_size+1, 2)) x_ticks = list(range(1, plot_size+1, 2))
x_labels = x_ticks[:] x_labels = x_ticks[:]
x_ticks.append(plot_size+1)
x_labels.append("total")
plt.xticks(x_ticks, x_labels) plt.xticks(x_ticks, x_labels)
plt.legend(legend, loc="best") plt.legend(legend, loc="best")
plt.show() plt.show()
graph_cmdSequences() # graph_cmdSequences()
graph_cmdSequences(node_count=28, edge_minValue=0.06) # graph_cmdSequences(node_count=28, edge_minValue=0.06)
#
plot_cmdLineFrq_rank() # plot_cmdLineFrq_rank()
# plot_cmdFrq_rank() # # plot_cmdFrq_rank()
#
plot_cmdLineVocabularySize_cmdLinesEntered() # plot_cmdLineVocabularySize_cmdLinesEntered()
# plot_cmdVocabularySize_cmdLinesEntered() # # plot_cmdVocabularySize_cmdLinesEntered()
plot_strategies_matches() plot_strategies_matches()
plot_strategies_charsRecalled() plot_strategies_charsRecalled()

@ -12,6 +12,7 @@ import (
"os/exec" "os/exec"
"os/user" "os/user"
"path/filepath" "path/filepath"
"sort"
"github.com/curusarn/resh/common" "github.com/curusarn/resh/common"
) )
@ -89,7 +90,12 @@ func main() {
// strategies = append(strategies, &dummy) // strategies = append(strategies, &dummy)
recent := strategyRecent{} recent := strategyRecent{}
strategies = append(strategies, &recent) frequent := strategyFrequent{}
frequent.init()
directory := strategyDirectorySensitive{}
directory.init()
strategies = append(strategies, &recent, &frequent, &directory)
for _, strat := range strategies { for _, strat := range strategies {
err := evaluator.evaluate(strat) err := evaluator.evaluate(strat)
@ -175,8 +181,18 @@ func (e *evaluator) calculateStatsAndPlot(scriptName string) {
// enrich records and add them to serializable structure // enrich records and add them to serializable structure
func (e *evaluator) processRecords() { func (e *evaluator) processRecords() {
for i := range e.UsersRecords { for i := range e.UsersRecords {
for j := range e.UsersRecords[i].Devices { for j, device := range e.UsersRecords[i].Devices {
sessionIDs := map[string]uint64{}
var nextID uint64
nextID = 0
for k, record := range e.UsersRecords[i].Devices[j].Records { for k, record := range e.UsersRecords[i].Devices[j].Records {
id, found := sessionIDs[record.SessionId]
if found == false {
id = nextID
sessionIDs[record.SessionId] = id
nextID++
}
record.SeqSessionID = id
// assert // assert
if record.Sanitized != e.sanitizedInput { if record.Sanitized != e.sanitizedInput {
if e.sanitizedInput { if e.sanitizedInput {
@ -188,6 +204,12 @@ func (e *evaluator) processRecords() {
e.UsersRecords[i].Devices[j].Records[k].Enrich() e.UsersRecords[i].Devices[j].Records[k].Enrich()
// device.Records = append(device.Records, record) // device.Records = append(device.Records, record)
} }
sort.SliceStable(e.UsersRecords[i].Devices[j].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
})
} }
} }
} }

@ -0,0 +1,42 @@
package main
import (
"github.com/curusarn/resh/common"
)
type strategyDirectorySensitive struct {
history map[string][]string
lastPwd string
}
func (s *strategyDirectorySensitive) init() {
s.history = map[string][]string{}
}
func (s *strategyDirectorySensitive) GetTitleAndDescription() (string, string) {
return "directory sensitive (recent)", "Use recent commands executed is the same directory"
}
func (s *strategyDirectorySensitive) GetCandidates() []string {
return s.history[s.lastPwd]
}
func (s *strategyDirectorySensitive) AddHistoryRecord(record *common.Record) 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
}
func (s *strategyDirectorySensitive) ResetHistory() error {
s.history = map[string][]string{}
return nil
}

@ -0,0 +1,47 @@
package main
import (
"sort"
"github.com/curusarn/resh/common"
)
type strategyFrequent struct {
history map[string]int
}
type strFrqEntry struct {
cmdLine string
count int
}
func (s *strategyFrequent) init() {
s.history = map[string]int{}
}
func (s *strategyFrequent) GetTitleAndDescription() (string, string) {
return "frequent", "Use frequent commands"
}
func (s *strategyFrequent) 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
}
func (s *strategyFrequent) AddHistoryRecord(record *common.Record) error {
s.history[record.CmdLine]++
return nil
}
func (s *strategyFrequent) ResetHistory() error {
s.history = map[string]int{}
return nil
}

@ -27,5 +27,6 @@ func (s *strategyRecent) AddHistoryRecord(record *common.Record) error {
} }
func (s *strategyRecent) ResetHistory() error { func (s *strategyRecent) ResetHistory() error {
s.history = nil
return nil return nil
} }

Loading…
Cancel
Save