@ -3,8 +3,9 @@ package main
import (
import (
"database/sql"
"database/sql"
"fmt"
"fmt"
// "log"
"log"
"github.com/goccy/go-graphviz/cgraph"
_ "github.com/mattn/go-sqlite3"
_ "github.com/mattn/go-sqlite3"
)
)
@ -21,7 +22,9 @@ func NewMapper(fn string) (AardMapper, error) {
}
}
type AardMapper struct {
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 ) {
func ( am AardMapper ) Areas ( ) ( map [ string ] Area , error ) {
@ -44,9 +47,69 @@ func (am AardMapper) Areas() (map[string]Area, error) {
return areas , nil
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 )
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;")
// 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 ( )
defer rows . Close ( )
@ -65,3 +128,45 @@ func (am AardMapper) Exits() ([]RoomExit, error) {
}
}
return exits , nil
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
}