Compare commits

..

No commits in common. "3695f2704b851fa0c562411ae5dd31a2e891d9ca" and "16f718dcdcd73cf3d1ab9ef6638db2a7ba24067d" have entirely different histories.

View File

@ -1,25 +1,11 @@
package main package main
import ( import (
"encoding/csv"
"flag"
"fmt" "fmt"
"git.chromaticdragon.app/kistaro/auctionsim/auctionsim" "git.chromaticdragon.app/kistaro/auctionsim/auctionsim"
"log" "log"
"math"
"math/rand"
"os" "os"
"strings" "strconv"
)
var (
bidders = flag.Int("b", 1000, "Number of bidders in each auction.")
runs = flag.Int("r", 1, "Number of auctions to run.")
errorDev = flag.Float64("d", 1.0, "Standard deviation of bidder irrationality.")
errorMean = flag.Float64("m", 0.0, "Mean of bidder irrationality. Negative values represent a bias towards underbidding.")
format = flag.String("f", "txt", "Output format: plain text (\"txt\") or CSV (\"csv\").")
) )
func deltaStr(delta float64) string { func deltaStr(delta float64) string {
@ -32,33 +18,25 @@ func deltaStr(delta float64) string {
return "broken even" return "broken even"
} }
func normalizeFormat() error { func main() {
*format = strings.ToLower(*format) num := int64(1000)
if *format == "txt" { if len(os.Args) > 1 {
return nil n, err := strconv.ParseInt(os.Args[1], 0, 64)
if err != nil {
log.Fatalf("can't parse %q as a number of bidders: %v", os.Args[1], err)
} }
if *format == "csv" { num = n
return nil
} }
return fmt.Errorf("unrecognized format: %q", *format) if num <= 1 {
} log.Fatalf("can't run an auction with %d bidders", num)
type emitter interface {
Emit(*auctionsim.ResultSummary)
Flush()
}
type textEmitter struct {
notFirst bool
}
func (t *textEmitter) Emit(summary *auctionsim.ResultSummary) {
if !t.notFirst {
fmt.Println()
fmt.Println("-----------------")
fmt.Println()
t.notFirst = true
} }
summary := auctionsim.Summarize(auctionsim.RunAuctionVerbosely(
&auctionsim.CappedBidderGenerator{
G: auctionsim.NormalestBidderGenerator(),
Lim: num,
},
))
fmt.Printf("The auction winner paid ¤%f. They have %s.\n", summary.Price, deltaStr(summary.WinnerProfit)) fmt.Printf("The auction winner paid ¤%f. They have %s.\n", summary.Price, deltaStr(summary.WinnerProfit))
fmt.Printf("The item was worth ¤%f to them.\n", summary.WinnerValue) fmt.Printf("The item was worth ¤%f to them.\n", summary.WinnerValue)
fmt.Printf("They would have paid up to ¤%f for it.\n", summary.WinnerMaxBid) fmt.Printf("They would have paid up to ¤%f for it.\n", summary.WinnerMaxBid)
@ -80,51 +58,3 @@ func (t *textEmitter) Emit(summary *auctionsim.ResultSummary) {
fmt.Printf("They valued it ¤%f more than the winning bidder.\n", summary.ValueDelta) fmt.Printf("They valued it ¤%f more than the winning bidder.\n", summary.ValueDelta)
} }
} }
func (*textEmitter) Flush() {}
type csvEmitter struct {
w *csv.Writer
}
func (c *csvEmitter) Emit(summary *auctionsim.ResultSummary) {
c.w.Write(summary.CSVRecord())
}
func (c *csvEmitter) Flush() {
c.w.Flush()
}
func main() {
flag.Parse()
if err := normalizeFormat(); err != nil {
log.Fatal(err)
}
e := emitter(&textEmitter{})
if *format == "csv" {
w := csv.NewWriter(os.Stdout)
e = &csvEmitter{w}
w.Write(auctionsim.ResultSummaryCSVHeader())
}
defer e.Flush()
for i := 0; i < *runs; i++ {
g := &auctionsim.BiddersFromDistributions{
Values: auctionsim.NormalestDistribution(),
Irrationalities: &auctionsim.NormalDistribution{
Rand: rand.New(rand.NewSource(int64(rand.Uint64()))),
StdDev: *errorDev,
Mean: *errorMean,
},
Bankrolls: auctionsim.ConstDistribution(math.Inf(1)),
}
e.Emit(auctionsim.Summarize(auctionsim.RunAuctionVerbosely(
&auctionsim.CappedBidderGenerator{
G: g,
Lim: int64(*bidders),
},
)))
}
}