mirror of https://github.com/curusarn/resh
because matplotlib is just too good and trying to plot in golang is not worth itpull/13/head
parent
939fb2f847
commit
6f7f505420
@ -0,0 +1,99 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"fmt" |
||||
"log" |
||||
"math" |
||||
"strconv" |
||||
) |
||||
|
||||
type results struct { |
||||
writer *bufio.Writer |
||||
size int |
||||
matches []int // matches[N] -> # of matches at distance N
|
||||
matchesTotal int |
||||
charactersRecalled []int |
||||
charactersRecalledTotal int |
||||
dataPointCount int |
||||
} |
||||
|
||||
func (r *results) init() { |
||||
r.matches = make([]int, r.size) |
||||
r.charactersRecalled = make([]int, r.size) |
||||
} |
||||
|
||||
func (r *results) addMatch(distance int, cmdLength int) { |
||||
if distance >= r.size { |
||||
// --calculate-total
|
||||
// log.Fatal("Match distance is greater than size of statistics")
|
||||
r.matchesTotal++ |
||||
r.charactersRecalledTotal += cmdLength |
||||
return |
||||
} |
||||
r.matches[distance]++ |
||||
r.matchesTotal++ |
||||
r.charactersRecalled[distance] += cmdLength |
||||
r.charactersRecalledTotal += cmdLength |
||||
r.dataPointCount++ |
||||
} |
||||
|
||||
func (r *results) addMiss() { |
||||
r.dataPointCount++ |
||||
} |
||||
|
||||
func (r *results) printCumulative() { |
||||
matchesPercent := 0.0 |
||||
out := "### Matches ###\n" |
||||
for i := 0; i < r.size; i++ { |
||||
matchesPercent += 100 * float64(r.matches[i]) / float64(r.dataPointCount) |
||||
out += strconv.Itoa(i) + " ->" |
||||
out += fmt.Sprintf(" (%.1f %%)\n", matchesPercent) |
||||
for j := 0; j < int(math.Round(matchesPercent)); j++ { |
||||
out += "#" |
||||
} |
||||
out += "\n" |
||||
} |
||||
matchesPercent = 100 * float64(r.matchesTotal) / float64(r.dataPointCount) |
||||
out += "TOTAL ->" |
||||
out += fmt.Sprintf(" (%.1f %%)\n", matchesPercent) |
||||
for j := 0; j < int(math.Round(matchesPercent)); j++ { |
||||
out += "#" |
||||
} |
||||
out += "\n" |
||||
|
||||
n, err := r.writer.WriteString(string(out) + "\n\n") |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
if n == 0 { |
||||
log.Fatal("Nothing was written", n) |
||||
} |
||||
|
||||
charsRecall := 0.0 |
||||
out = "### Characters recalled per submission ###\n" |
||||
for i := 0; i < r.size; i++ { |
||||
charsRecall += float64(r.charactersRecalled[i]) / float64(r.dataPointCount) |
||||
out += strconv.Itoa(i) + " ->" |
||||
out += fmt.Sprintf(" (%.2f)\n", charsRecall) |
||||
for j := 0; j < int(math.Round(charsRecall)); j++ { |
||||
out += "#" |
||||
} |
||||
out += "\n" |
||||
} |
||||
charsRecall = float64(r.charactersRecalledTotal) / float64(r.dataPointCount) |
||||
out += "TOTAL ->" |
||||
out += fmt.Sprintf(" (%.2f)\n", charsRecall) |
||||
for j := 0; j < int(math.Round(charsRecall)); j++ { |
||||
out += "#" |
||||
} |
||||
out += "\n" |
||||
|
||||
n, err = r.writer.WriteString(string(out) + "\n\n") |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
if n == 0 { |
||||
log.Fatal("Nothing was written", n) |
||||
} |
||||
} |
||||
@ -1,99 +1,117 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"fmt" |
||||
"bytes" |
||||
"io/ioutil" |
||||
"log" |
||||
"math" |
||||
"strconv" |
||||
"sort" |
||||
|
||||
"github.com/wcharczuk/go-chart" |
||||
) |
||||
|
||||
type statistics struct { |
||||
writer *bufio.Writer |
||||
size int |
||||
matches []int |
||||
matchesTotal int |
||||
charactersRecalled []int |
||||
charactersRecalledTotal int |
||||
//size int
|
||||
dataPointCount int |
||||
cmdLineCount map[string]int |
||||
} |
||||
|
||||
func (s *statistics) init() { |
||||
s.matches = make([]int, s.size) |
||||
s.charactersRecalled = make([]int, s.size) |
||||
s.cmdLineCount = make(map[string]int) |
||||
} |
||||
|
||||
func (s *statistics) addMatch(distance int, cmdLength int) { |
||||
if distance >= s.size { |
||||
// --calculate-total
|
||||
// log.Fatal("Match distance is greater than size of statistics")
|
||||
s.matchesTotal++ |
||||
s.charactersRecalledTotal += cmdLength |
||||
return |
||||
} |
||||
s.matches[distance]++ |
||||
s.matchesTotal++ |
||||
s.charactersRecalled[distance] += cmdLength |
||||
s.charactersRecalledTotal += cmdLength |
||||
func (s *statistics) addCmdLine(cmdLine string, cmdLength int) { |
||||
s.cmdLineCount[cmdLine]++ |
||||
s.dataPointCount++ |
||||
} |
||||
|
||||
func (s *statistics) addMiss() { |
||||
s.dataPointCount++ |
||||
} |
||||
func (s *statistics) graphCmdFrequencyAsFuncOfRank() { |
||||
|
||||
func (s *statistics) printCumulative() { |
||||
matchesPercent := 0.0 |
||||
out := "### Matches ###\n" |
||||
for i := 0; i < s.size; i++ { |
||||
matchesPercent += 100 * float64(s.matches[i]) / float64(s.dataPointCount) |
||||
out += strconv.Itoa(i) + " ->" |
||||
out += fmt.Sprintf(" (%.1f %%)\n", matchesPercent) |
||||
for j := 0; j < int(math.Round(matchesPercent)); j++ { |
||||
out += "#" |
||||
} |
||||
out += "\n" |
||||
var xValues []float64 |
||||
var yValues []float64 |
||||
|
||||
sortedValues := sortMapByvalue(s.cmdLineCount) |
||||
sortedValues = sortedValues[:100] // cut off at rank 100
|
||||
|
||||
normalizeCoeficient := float64(s.dataPointCount) / float64(sortedValues[0].Value) |
||||
for i, pair := range sortedValues { |
||||
rank := i + 1 |
||||
frequency := float64(pair.Value) / float64(s.dataPointCount) |
||||
normalizeFrequency := frequency * normalizeCoeficient |
||||
|
||||
xValues = append(xValues, float64(rank)) |
||||
yValues = append(yValues, normalizeFrequency) |
||||
} |
||||
matchesPercent = 100 * float64(s.matchesTotal) / float64(s.dataPointCount) |
||||
out += "TOTAL ->" |
||||
out += fmt.Sprintf(" (%.1f %%)\n", matchesPercent) |
||||
for j := 0; j < int(math.Round(matchesPercent)); j++ { |
||||
out += "#" |
||||
|
||||
graphName := "cmdFrqAsFuncOfRank" |
||||
graph := chart.Chart{ |
||||
XAxis: chart.XAxis{ |
||||
Style: chart.StyleShow(), //enables / displays the x-axis
|
||||
Ticks: []chart.Tick{ |
||||
{0.0, "0"}, |
||||
{1.0, "1"}, |
||||
{2.0, "2"}, |
||||
{3.0, "3"}, |
||||
{4.0, "4"}, |
||||
{5.0, "5"}, |
||||
{10.0, "10"}, |
||||
{15.0, "15"}, |
||||
{20.0, "20"}, |
||||
{25.0, "25"}, |
||||
{30.0, "30"}, |
||||
{35.0, "35"}, |
||||
{40.0, "40"}, |
||||
{45.0, "45"}, |
||||
{50.0, "50"}, |
||||
}, |
||||
}, |
||||
YAxis: chart.YAxis{ |
||||
AxisType: chart.YAxisSecondary, |
||||
Style: chart.StyleShow(), //enables / displays the y-axis
|
||||
}, |
||||
Series: []chart.Series{ |
||||
chart.ContinuousSeries{ |
||||
Style: chart.Style{ |
||||
Show: true, |
||||
StrokeColor: chart.GetDefaultColor(0).WithAlpha(64), |
||||
FillColor: chart.GetDefaultColor(0).WithAlpha(64), |
||||
DotColor: chart.GetDefaultColor(0), |
||||
DotWidth: 3.0, |
||||
}, |
||||
XValues: xValues, |
||||
YValues: yValues, |
||||
}, |
||||
}, |
||||
} |
||||
out += "\n" |
||||
|
||||
n, err := s.writer.WriteString(string(out) + "\n\n") |
||||
buffer := bytes.NewBuffer([]byte{}) |
||||
err := graph.Render(chart.PNG, buffer) |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
log.Fatal("chart.Render error:", err) |
||||
} |
||||
if n == 0 { |
||||
log.Fatal("Nothing was written", n) |
||||
ioutil.WriteFile("/tmp/resh-graph_"+graphName+".png", buffer.Bytes(), 0644) |
||||
} |
||||
|
||||
charsRecall := 0.0 |
||||
out = "### Characters recalled per submission ###\n" |
||||
for i := 0; i < s.size; i++ { |
||||
charsRecall += float64(s.charactersRecalled[i]) / float64(s.dataPointCount) |
||||
out += strconv.Itoa(i) + " ->" |
||||
out += fmt.Sprintf(" (%.2f)\n", charsRecall) |
||||
for j := 0; j < int(math.Round(charsRecall)); j++ { |
||||
out += "#" |
||||
} |
||||
out += "\n" |
||||
} |
||||
charsRecall = float64(s.charactersRecalledTotal) / float64(s.dataPointCount) |
||||
out += "TOTAL ->" |
||||
out += fmt.Sprintf(" (%.2f)\n", charsRecall) |
||||
for j := 0; j < int(math.Round(charsRecall)); j++ { |
||||
out += "#" |
||||
} |
||||
out += "\n" |
||||
func sortMapByvalue(input map[string]int) []Pair { |
||||
p := make(PairList, len(input)) |
||||
|
||||
n, err = s.writer.WriteString(string(out) + "\n\n") |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
i := 0 |
||||
for k, v := range input { |
||||
p[i] = Pair{k, v} |
||||
i++ |
||||
} |
||||
if n == 0 { |
||||
log.Fatal("Nothing was written", n) |
||||
sort.Sort(sort.Reverse(p)) |
||||
return p |
||||
} |
||||
|
||||
// Pair - A data structure to hold key/value pairs
|
||||
type Pair struct { |
||||
Key string |
||||
Value int |
||||
} |
||||
|
||||
// PairList - A slice of pairs that implements sort.Interface to sort by values
|
||||
type PairList []Pair |
||||
|
||||
func (p PairList) Len() int { return len(p) } |
||||
func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } |
||||
func (p PairList) Less(i, j int) bool { return p[i].Value < p[j].Value } |
||||
|
||||
@ -1,4 +1,13 @@ |
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= |
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= |
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= |
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= |
||||
github.com/mattn/go-shellwords v1.0.6 h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3ZkeUUI= |
||||
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= |
||||
github.com/wcharczuk/go-chart v2.0.1+incompatible h1:0pz39ZAycJFF7ju/1mepnk26RLVLBCWz1STcD3doU0A= |
||||
github.com/wcharczuk/go-chart v2.0.1+incompatible/go.mod h1:PF5tmL4EIx/7Wf+hEkpCqYi5He4u90sw+0+6FhrryuE= |
||||
github.com/whilp/git-urls v0.0.0-20160530060445-31bac0d230fa h1:rW+Lu6281ed/4XGuVIa4/YebTRNvoUJlfJ44ktEVwZk= |
||||
github.com/whilp/git-urls v0.0.0-20160530060445-31bac0d230fa/go.mod h1:2rx5KE5FLD0HRfkkpyn8JwbVLBdhgeiOb2D2D9LLKM4= |
||||
golang.org/x/image v0.0.0-20190902063713-cb417be4ba39 h1:4dQcAORh9oYBwVSBVIkP489LUPC+f1HBkTYXgmqfR+o= |
||||
golang.org/x/image v0.0.0-20190902063713-cb417be4ba39/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= |
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
||||
|
||||
Loading…
Reference in new issue