func doFlowGraph(cmd string, args []string) { fs := flag.NewFlagSet("flowgraph", flag.ExitOnError) fs.Usage = func() { log.Print("Usage: flowgraph") log.Printf("%v\n", cmds.Help(cmd)) fs.PrintDefaults() } proto := fs.Bool("proto", false, "aggregate nodes by prototype") t0 := fs.Int("t1", 0, "beginning of time interval (default is beginning of simulation)") t1 := fs.Int("t2", -1, "end of time interval (default if end of simulation)") fs.Parse(args) initdb() arcs, err := query.FlowGraph(db, simid, *t0, *t1, *proto) fatalif(err) fmt.Println("digraph ResourceFlows {") fmt.Println(" overlap = false;") fmt.Println(" nodesep=1.0;") fmt.Println(" edge [fontsize=9];") for _, arc := range arcs { fmt.Printf(" \"%v\" -> \"%v\" [label=\"%v\\n(%.3g kg)\"];\n", arc.Src, arc.Dst, arc.Commod, arc.Quantity) } fmt.Println("}") }
func uploadInner(w http.ResponseWriter, r *http.Request, kill chan bool) { // parse database from multi part form data if err := r.ParseMultipartForm(MAX_MEMORY); err != nil { log.Println(err) http.Error(w, err.Error(), http.StatusForbidden) return } gotDb := false uid := r.URL.Path[len("/upload/"):] fname := uid + ".sqlite" for _, fileHeaders := range r.MultipartForm.File { for _, fileHeader := range fileHeaders { file, _ := fileHeader.Open() data, _ := ioutil.ReadAll(file) err := ioutil.WriteFile(fname, data, 0644) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } defer func() { os.Remove(fname) }() gotDb = true break } break } if !gotDb { http.Error(w, "No file provided", http.StatusBadRequest) log.Print("received request with no file") return } select { case <-kill: return default: } // post process the database db, err := sql.Open("sqlite3", fname) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } defer db.Close() err = post.Prepare(db) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } defer post.Finish(db) simids, err := post.GetSimIds(db) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } ctx := post.NewContext(db, simids[0]) if err := ctx.WalkAll(); err != nil { log.Println(err) } // get simid ids, err := query.SimIds(db) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } simid := ids[0] rs := &Results{} select { case <-kill: return default: } // create flow graph combineProto := false arcs, err := query.FlowGraph(db, simid, 0, -1, combineProto) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } dotname := fname + ".dot" dotf, err := os.Create(dotname) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } defer func() { os.Remove(dotname) }() fmt.Fprintln(dotf, "digraph ResourceFlows {") fmt.Fprintln(dotf, " overlap = false;") fmt.Fprintln(dotf, " nodesep=1.0;") fmt.Fprintln(dotf, " edge [fontsize=9];") for _, arc := range arcs { fmt.Fprintf(dotf, " \"%v\" -> \"%v\" [label=\"%v\\n(%.3g kg)\"];\n", arc.Src, arc.Dst, arc.Commod, arc.Quantity) } fmt.Fprintln(dotf, "}") dotf.Close() var buf bytes.Buffer cmd := exec.Command("dot", "-Tsvg", dotname) cmd.Stdout = &buf err = cmd.Run() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } rs.Flowgraph = buf.String() select { case <-kill: return default: } // create agents table rs.Agents, err = query.AllAgents(db, simid, "") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } // create Material transactions table sql := ` SELECT TransactionId,Time,SenderId,ReceiverId,tr.ResourceId,Commodity,NucId,MassFrac*Quantity FROM Transactions AS tr INNER JOIN Resources AS res ON tr.ResourceId = res.ResourceId INNER JOIN Compositions AS cmp ON res.QualId = cmp.QualId WHERE tr.SimId = ? AND cmp.SimId = res.SimId AND res.SimId = tr.SimId AND res.Type = 'Material'; ` rows, err := db.Query(sql, simid) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } for rows.Next() { t := &Trans{} if err := rows.Scan(&t.Id, &t.Time, &t.Sender, &t.Receiver, &t.ResourceId, &t.Commod, &t.Nuc, &t.Qty); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } rs.TransMats = append(rs.TransMats, t) } if err := rows.Err(); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } // create Material transactions table sql = ` SELECT TransactionId,Time,SenderId,ReceiverId,tr.ResourceId,Commodity,Quality,Quantity FROM Transactions AS tr INNER JOIN Resources AS res ON tr.ResourceId = res.ResourceId INNER JOIN Products AS pd ON res.QualId = pd.QualId WHERE tr.SimId = ? AND pd.SimId = res.SimId AND res.SimId = tr.SimId AND res.Type = 'Product'; ` rows, err = db.Query(sql, simid) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } for rows.Next() { t := &ProdTrans{} if err := rows.Scan(&t.Id, &t.Time, &t.Sender, &t.Receiver, &t.ResourceId, &t.Commod, &t.Quality, &t.Qty); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } rs.TransProds = append(rs.TransProds, t) } if err := rows.Err(); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } select { case <-kill: return default: } // render all results and save page rs.Uid = uid resultTmpl.Execute(w, rs) f, err := os.Create(uid + ".html") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) return } defer f.Close() resultTmpl.Execute(f, rs) close(kill) }
func doTaint(cmd string, args []string) { fs := flag.NewFlagSet(cmd, flag.ExitOnError) fs.Usage = func() { log.Printf("Usage: %v", cmd) log.Printf("%v\n", cmds.Help(cmd)) fs.PrintDefaults() } t := fs.Int("t", -1, "time step for which to print taint") res := fs.Int("res", -1, "resource ID of object to track") fs.Parse(args) initdb() if *t == -1 || *res == -1 { log.Fatalf("'-t' and '-res' flags are both required and cannot be negative") } roots := taint.TreeFromDb(db, simid) var base *taint.Node visited := taint.Visited{} for _, root := range roots { if base = root.Locate(visited, *res); base != nil { break } } if base == nil { log.Fatalf("couldn't find resource id %v in graph", *res) } si, err := query.SimStat(db, simid) fatalif(err) taints := base.Taint(si.Duration) // print graph dot file byproto := false t1, t2 := 0, -1 arcs, err := query.FlowGraph(db, simid, t1, t2, byproto) fatalif(err) fmt.Println("digraph ResourceFlows {") fmt.Println(" overlap = false;") fmt.Println(" nodesep=1.0;") fmt.Println(" edge [fontsize=9];") for _, arc := range arcs { var srctaint taint.TaintVal if ts := taints[arc.SrcId]; *t < len(ts) { srctaint = ts[*t] } else if len(ts) > 0 { srctaint = ts[len(ts)-1] } var dsttaint taint.TaintVal if ts := taints[arc.DstId]; *t < len(ts) { dsttaint = ts[*t] } else if len(ts) > 0 { dsttaint = ts[len(ts)-1] } srccolor := byte(255 * (1 - math.Pow(srctaint.Taint*srctaint.Quantity/base.Quantity, 1.0/5))) dstcolor := byte(255 * (1 - math.Pow(dsttaint.Taint*dsttaint.Quantity/base.Quantity, 1.0/5))) srcname := fmt.Sprintf("%v %v\\n(%.3e kg of %.4f taint)", arc.SrcProto, arc.SrcId, srctaint.Quantity, srctaint.Taint) dstname := fmt.Sprintf("%v %v\\n(%.3e kg of %.4f taint)", arc.DstProto, arc.DstId, dsttaint.Quantity, dsttaint.Taint) fmt.Printf(" \"%v\" [style=filled, fillcolor=\"#FF%.2X%.2X\"];\n", srcname, srccolor, srccolor) fmt.Printf(" \"%v\" [style=filled, fillcolor=\"#FF%.2X%.2X\"];\n", dstname, dstcolor, dstcolor) fmt.Printf(" \"%v\" -> \"%v\" [label=\"%v\"];\n", srcname, dstname, arc.Commod) } fmt.Println("}") }