reorganizing my approach

instead of working by RoomExit, I'll just go room by room, exit by exit.

gave Room a String() method for my sanity

no longer trying to load everything into memory in one big batch
main
Nick Dumas 2 years ago
parent d9671822b7
commit 89db3af1b8

@ -2,8 +2,10 @@ package main
import (
"flag"
// "fmt"
"log"
// "github.com/goccy/go-graphviz"
"github.com/goccy/go-graphviz"
_ "github.com/mattn/go-sqlite3"
)
@ -22,14 +24,39 @@ func main() {
}
// log.Printf("databse opened: %#+v\n", am)
exits, err := am.Exits()
gv := graphviz.New()
if err != nil {
log.Fatalf("error opening graph: %s\n", err)
}
g, err := gv.Graph()
if err != nil {
log.Fatalf("error fetching Rooms: %s\n", err)
log.Fatalf("error retrieving cgraph: %s\n", err)
}
for _, v := range exits {
/*
x, err := am.Room("673")
if err != nil {
log.Fatalf("error querying room: %s", err)
}
log.Printf("%#+v\n", x)
return
*/
rooms, err := am.Rooms()
log.Printf("rooms found: %d\n", len(rooms))
for _, room := range rooms[:50] {
log.Printf("main() %s\n", room)
// log.Printf("Area: %#+v\n", v)
log.Printf("RoomExit found: %s\n", v)
break
// log.Printf("RoomExit found: %s\n", v)
err := am.Walk(room.Uid.String, g)
if err != nil {
log.Fatalf("error adding room to graph: %s\n", err)
}
}
log.Printf("exit count: %d\n", g.NumberEdges())
log.Printf("room count: %d\n", g.NumberNodes())
if err := gv.RenderFilename(g, graphviz.SVG, "/var/www/renders.ndumas.com/aardmaps/final.svg"); err != nil {
log.Fatal(err)
}
// now that I have areas and rooms, I can start building a map

@ -3,8 +3,9 @@ package main
import (
"database/sql"
"fmt"
// "log"
"log"
"github.com/goccy/go-graphviz/cgraph"
_ "github.com/mattn/go-sqlite3"
)
@ -21,7 +22,9 @@ func NewMapper(fn string) (AardMapper, error) {
}
type AardMapper struct {
DB *sql.DB
DB *sql.DB
RoomCache map[string]Room
AreaCache map[string]Area
}
func (am AardMapper) Areas() (map[string]Area, error) {
@ -44,9 +47,69 @@ func (am AardMapper) Areas() (map[string]Area, error) {
return areas, nil
}
func (am AardMapper) Exits() ([]RoomExit, error) {
func (am AardMapper) Area(uid string) (Area, error) {
a, ok := am.AreaCache[uid]
if ok {
return a, nil
}
a = Area{}
row := am.DB.QueryRow("select uid, name, flags, color, texture from areas where uid = :uid")
if err := row.Scan(&a.Uid, &a.Name, &a.Flags, &a.Color, &a.Texture); err != nil {
if err == sql.ErrNoRows {
return a, fmt.Errorf("no area found: %w", err)
}
}
return a, nil
}
func (am AardMapper) Rooms() ([]Room, error) {
var uidCount int
uidCountRow := am.DB.QueryRow("select count(uid) from rooms;")
uidCountRow.Scan(&uidCount)
log.Println("uidCount:", uidCount)
rows, err := am.DB.Query("select uid from rooms;")
if err != nil {
return nil, fmt.Errorf("error querying room UIDs: %w", err)
}
var uids = make([]string, uidCount)
i := 0
for rows.Next() {
var uid string
if err := rows.Scan(&uid); err != nil {
return nil, fmt.Errorf("error querying room %q from uid: %w", uid, err)
}
uids[i] = uid
}
rooms := make([]Room, uidCount)
for idx, uid := range uids {
room, err := am.Room(uid)
if err != nil {
return rooms, fmt.Errorf("error fetching room: %s", err)
}
rooms[idx] = room
}
return rooms, nil
}
func (am AardMapper) Room(uid string) (Room, error) {
r := Room{}
row := am.DB.QueryRow("select uid,name,building,info,notes,flags,area,norecall,noportal from rooms where uid = ?", uid)
if err := row.Scan(&r.Uid, &r.Name, &r.Building, &r.Info, &r.Notes, &r.Flags, &r.AreaName, &r.Norecall, &r.Noportal); err != nil {
if err == sql.ErrNoRows {
return r, fmt.Errorf("no room found: %w", err)
}
log.Println("room found:", r.Uid.String)
}
return r, nil
}
func (am AardMapper) Exits(uid string) ([]RoomExit, error) {
exits := make([]RoomExit, 0)
rows, err := am.DB.Query("select r.uid,r.name,r.building,r.info,r.notes,r.flags,r.area, r.norecall,r.noportal,e.dir,e.fromuid,e.touid,e.level from rooms r INNER JOIN exits e ON r.uid = e.fromuid;")
rows, err := am.DB.Query("select r.uid,r.name,r.building,r.info,r.notes,r.flags,r.area, r.norecall,r.noportal,e.dir,e.fromuid,e.touid,e.level from rooms r INNER JOIN exits e ON r.uid = e.fromuid where uid=:uid;", uid)
// rows, err := am.DB.Query("select e.dir,e.fromuid,e.touid,e.level from rooms r INNER JOIN exits e ON r.uid = e.fromuid;")
defer rows.Close()
@ -65,3 +128,45 @@ func (am AardMapper) Exits() ([]RoomExit, error) {
}
return exits, nil
}
func (am AardMapper) Walk(uid string, g *cgraph.Graph) error {
originRoom, err := am.Room(uid)
if err != nil {
return fmt.Errorf("error querying origin room for walk %q: %w", uid, err)
}
area, err := am.Area(originRoom.AreaName.String)
if err != nil {
return fmt.Errorf("error querying origin area for walk %q: %w", uid, err)
}
sg := g.SubGraph("cluster_"+area.Name.String, 1)
sg.SetLabel(area.Name.String)
originNode, err := sg.CreateNode(originRoom.Uid.String)
if err != nil {
return fmt.Errorf("error creating origin node for room %s: %w", originRoom.Name.String, err)
}
sg.SetLabel(originRoom.Name.String)
exits, err := am.Exits(originRoom.Uid.String)
if err != nil {
return fmt.Errorf("error fetching exits for origin room %s: %w", originRoom.Name.String, err)
}
for _, exit := range exits {
destRoom, err := am.Room(exit.Touid.String)
if err != nil {
return fmt.Errorf("error querying destination room %s: %w", uid, err)
}
destNode, err := sg.CreateNode(destRoom.Uid.String)
destNode.SetLabel(destRoom.Name.String)
if err != nil {
return fmt.Errorf("error creating destination node for room %s: %w", originRoom.Name.String, err)
}
// maybe i'll save recursion for later
// am.Walk(exit.Touid.String, g) // gotta prevent cycles. check if edge already exists and return?
sg.CreateEdge(originRoom.Uid.String+">"+originRoom.Uid.String, originNode, destNode)
}
return nil
}

@ -17,6 +17,10 @@ type Room struct {
Exits []Exit
}
func (r Room) String() string {
return fmt.Sprintf("{Room:%q[%q]}", r.Name.String, r.Uid.String)
}
type Exit struct {
Dir sql.NullString
Fromuid, Touid sql.NullString

@ -1,14 +1,27 @@
package main
import (
"fmt"
// "github.com/goccy/go-graphviz"
"github.com/goccy/go-graphviz/cgraph"
)
func walk(r Room, parent *cgraph.Node, g *cgraph.Graph) error {
_, err := g.CreateNode(r.Uid.String)
func walk(re RoomExit, g *cgraph.Graph) error {
sg := g.SubGraph("cluster_"+re.Name.String, 1)
sg.SetLabel(re.Name.String)
origin, err := sg.CreateNode(re.Fromuid.String)
origin.SetLabel(re.Name.String)
if err != nil {
return fmt.Errorf("error creating origin node: %w", err)
}
dest, err := sg.CreateNode(re.Touid.String)
if err != nil {
return fmt.Errorf("error creating destination node: %w", err)
}
_, err = g.CreateEdge(re.String(), origin, dest)
if err != nil {
return err
return fmt.Errorf("error creating edge between origin and destination: %w", err)
}
return nil

Loading…
Cancel
Save