diff --git a/item.go b/item.go new file mode 100644 index 0000000..7030deb --- /dev/null +++ b/item.go @@ -0,0 +1,299 @@ +package main + +var ( + muxObjItem sync.RWMutex + objItems []ChatWarsItem + cacheObjItem map[string]int64 + cacheObjItemId map[int64]int64 +) + +func addObjItem(code string, name string, itemTypeID64 int64, weight int64, exchange string, auction bool) (int64, error) { + tx, err := db.Begin() + logOnError(err, "addObjItem : start transaction") + if err != nil { + return 0, err + } + + res, err := tx.Exec(`INSERT INTO obj (obj_type_id, obj_sub_type_id) + VALUES (` + strconv.FormatInt(cacheObjType[`item`], 10) + `,` + fmt.Sprintf("%d", itemTypeID64) + `);`) + logOnError(err, "addObjItem : exec insert obj ("+code+", "+name+")") + if err != nil { + err2 := tx.Rollback() + logOnError(err2, "addObjItem : rollback insert obj") + return 0, err + } + + objId, err := res.LastInsertId() + if err != nil { + err2 := tx.Rollback() + logOnError(err2, "addObjItem : rollback get lastInsertId") + return 0, err + } + + stmt, err := tx.Prepare(`INSERT INTO obj_item (obj_id, intl_id, weight, exchange, auction) + VALUES (?, ?, ?, ?, ?);`) + logOnError(err, "addObjItem : prepare insert obj_item") + if err != nil { + err2 := tx.Rollback() + logOnError(err2, "addObjItem : rollback prepare insert obj_item") + return 0, err + } + defer stmt.Close() + + var e, a int + if exchange != `` { + e = 1 + } else { + e = 0 + } + if auction { + a = 1 + } else { + a = 0 + } + + _, err = stmt.Exec(objId, code, weight, e, a) + logOnError(err, "addObjItem : exec insert obj_item") + if err != nil { + err2 := tx.Rollback() + logOnError(err2, "addObjItem : rollback exec insert obj_item") + return 0, err + } + + err = tx.Commit() + logOnError(err, "addObjItem : commit") + if err != nil { + return 0, err + } + + err = objAddName(objId, name) + logOnError(err, "addObjItem : add name") + + return objId, nil +} + +func getObjItem(objID64 int64) (*ChatWarsItem, error) { + muxObjItem.RLock() + defer muxObjItem.RUnlock() + if id, ok := cacheObjItemId[objID64]; ok { + //log.Printf("Matching item name %s with %s.\n", name, obj.Name) + return &objItems[id], nil + } else { + return nil, errors.New("Item not found.") + } +} + +func getObjItemID(c string, n string) int64 { + return getVerboseObjItemID(c, n) +} + +func getVerboseObjItemID(c string, n string) int64 { + i := getObjItemID(c, n) + if i == 0 { + w := TGCommand{ + Type: commandSendMsg, + Text: fmt.Sprintf("Object unknown : %s - %s\n", c, n), + ToUserID64: cfg.Bot.Admin, + } + TGCmdQueue <- w + } + return i +} + +func getSilentObjItemID(code string, name string) int64 { + muxObjItem.RLock() + defer muxObjItem.RUnlock() + if len(code) > 0 { + if id, ok := cacheObjItem[code]; ok { + //log.Printf("Matching item code %s with %s.\n", code, obj.Code) + return objItems[id].ObjID64 + } + if ok, _ := regexp.MatchString(`^(a|w)[0-9]+[a-e]$`, code); ok { + // log.Printf("Matching quality item code %s with %s.\n", code, code[:len(code)-1]) + if id, ok := cacheObjItem[code[:len(code)-1]]; ok { + return objItems[id].ObjID64 + } + } + if ok, _ := regexp.MatchString(`^u[0-9]+`, code); !ok { + return 0 + } + } + if len(name) == 0 { + return 0 + } + if id, ok := cacheObjItem[name]; ok { + //log.Printf("Matching item name %s with %s.\n", name, obj.Name) + return objItems[id].ObjID64 + } + if ok, _ := regexp.MatchString(`^((u|e)[0-9]+|(a|w)[0-9]+[a-e]{0,1})$`, code); ok || len(code) == 0 { + r := regexp.MustCompile(`^((?P⚡\+[0-9]+) ){0,1}(?P.+?)( \+(?P[0-9]+)⚔){0,1}( \+(?P[0-9]+)🛡){0,1}( \+(?P[0-9]+)💧){0,1}$`) + basename := r.ReplaceAllString(name, "${BaseName}") + if id, ok := cacheObjItem[basename]; ok && len(basename) > 0 { + //log.Printf("Matching item full basename %s with %s.\n", basename, obj.Name) + return objItems[id].ObjID64 + } + i := -1 + for _, id := range cacheObjItem { + if ok, _ := regexp.MatchString(`^(a|e|w)[0-9]+$`, objItems[id].Code); ok { //only gear can be custom named + m := fmt.Sprintf("^((%s.*)|(.*%s))$", regexp.QuoteMeta(objItems[id].Names[0]), regexp.QuoteMeta(objItems[id].Names[0])) + if ok, _ := regexp.MatchString(m, basename); ok { + //log.Printf("LOOP : Matching item modified basename %s with %s (%d).\n", basename, item.Name, item.ObjID64) + i = id + break + } + } + } + + if i != -1 { + //log.Printf("RETURN : Matching item modified basename %s with %s (%d).\n", basename, item.Name, item.ObjID64) + return objItems[i].ObjID64 + } else { + /* + fmt.Printf("silentGetObjItemID : Modifier : `%s`\n", r.ReplaceAllString(name, "${Modifier}")) + fmt.Printf("silentGetObjItemID : BaseName : `%s`\n", r.ReplaceAllString(name, "${BaseName}")) + fmt.Printf("silentGetObjItemID : Atk : `%s`\n", r.ReplaceAllString(name, "${Atk}")) + fmt.Printf("silentGetObjItemID : Def : `%s`\n", r.ReplaceAllString(name, "${Def}")) + fmt.Printf("silentGetObjItemID : Mana : `%s`\n", r.ReplaceAllString(name, "${Mana}")) + */ + } + + } + return 0 + +} + +func setObjItemWeight(objID64 int64, weight int64) error { + log.Printf("setObjItemWeight[%d] : %d\n", objID64, weight) + stmt, err := db.Prepare(`UPDATE obj_item oi SET oi.weight = ? WHERE oi.obj_id = ?;`) + logOnError(err, "setObjItemWeight : prepare update obj_item") + if err != nil { + return err + } + defer stmt.Close() + + _, err = stmt.Exec(weight, objID64) + logOnError(err, fmt.Sprintf("setObjItemWeight : update obj_item(%d)", jobID64)) + if err != nil { + return err + } + return nil +} + +func loadObjItem() error { + var ( + obj_id int64 + type_id int64 + intl_id string + name string + weight int64 + ) + + muxObjItem.Lock() + defer muxObjItem.Unlock() + cacheObjItem = make(map[string]int64) + cacheObjItemId = make(map[int64]int64) + objItems = make([]ChatWarsItem, 0) + + b, err := Asset("data/obj_item.json") + logOnError(err, "loadObjItem : load data/obj_item.json") + if err != nil { + return err + } + + err = json.Unmarshal(b, &objItems) + var k int64 + for k = 0; k < len(objItems); k++ { + if len(objItems[k].Names) == 0 { + log.Printf("loadObjItems : %s : name missing.\n", objItems[k].Code) + } else { + if id, ok := cacheObjItem[objItems[k].Code]; ok { + log.Printf("loadObjItem : %s : duplicate code found. Belong to %s\n", objItems[id].Code, obj.Names[0]) + } else { + cacheObjItem[objItems[k].Code] = k + objItems[k].ItemTypeID = cacheObjSubType[i.ItemType] + + for _, n := range objItems[k].Names { + if id, ok := cacheObjItem[n]; ok { + log.Printf("loadObjItem : %s - %s : duplicate name found. Belongs to %s\n", objItems[k].Code, n, objItems[id].Code) + } else { + cacheObjItem[n] = k + } + } + } + } + } + + objs, err := db.Query(`SELECT oi.obj_id, o.obj_sub_type_id, oi.intl_id, oi.weight FROM obj o, obj_item oi WHERE o.id = oi.obj_id;`) + if err != nil { + logOnError(err, "loadObjItem : querying items") + return err + } + defer objs.Close() + + for objs.Next() { + err = objs.Scan(&obj_id, &type_id, &intl_id, &weight) + if err != nil { + logOnError(err, "loadObjItem : scanning items") + return err + } + + if id, ok := cacheObjItem[intl_id]; !ok { + log.Printf("loadObjItem : %s : orphaned item in database (id : %d)\n", intl_id, obj_id) + } else { + objItems[id].ObjID64 = obj_id + + if weight != obj.Weight { + log.Printf("loadObjItem : %s - %s : weight changed : %d => %d\n", objItems[id].Code, objItems[id].Names[0], weight, objItems[id].Weight) + setObjItemWeight(obj_id, objItems[id].weight) + } + + cacheObjItemId[obj_id] = id + } + } + + names, err := db.Query(`SELECT oi.obj_id, obn.name FROM obj_item oi, obj_name obn WHERE oi.obj_id = obn.obj_id;`) + if err != nil { + logOnError(err, "loadObjItem : querying names") + return err + } + defer names.Close() + + for names.Next() { + err = names.Scan(&obj_id, &name) + if err != nil { + logOnError(err, "loadObjItem : scanning names") + return err + } + if _, ok := cacheObjItem[name]; !ok { + if id, ok := cacheObjItemId[obj_id]; ok { + log.Printf("loadObjItem : %s : orphaned name in database for item %s\n", name, objItems[id].Code) + } + } + } + + for _, i := range cacheObjItem { + if objItems[i].ObjID64 == 0 { + id, _ := addObjItem(objItems[i].Code, objItems[i].Names[0], objItems[i].ItemTypeID, objItems[i].Weight, objItems[i].Exchange, objItems[i].Auction) + objItems[i].ObjID64 = id + cacheObjItemId[id] = i + for _, n := range objItems[i].Names { + objAddName(id, n) + cacheObjItem[n] = id + } + } + } + + log.Printf("%d items loaded.\n", len(items)) + + /* + for _, v := range cacheObjItemId { + log.Printf("Item cached : %d\n", v.ObjID64) + for _, n := range v.Names { + log.Printf("cacheObjItemId[%d] : %s : %s.\n", v.ObjID64, v.Names[0], n) + } + } + */ + + return nil + +}