Archived
1

Add pokememes info, convert it to new format and drop unnecessary database tables

This commit introduces pokememes information storage in source code (because they're rarely changed and I always update them manually).

All information about pokememes updated after nerf of 25 April. Also, added buttons to /pokedeks command for changing pages (there are 21 pages already!), and limited one page to 35 pokememes.
This commit is contained in:
2018-05-02 00:47:55 +04:00
parent b1975a161c
commit a9f1d25c7b
46 changed files with 10391 additions and 722 deletions

View File

@@ -45,18 +45,21 @@ type DataCacheInterface interface {
GetProfileByID(profileID int) (*dbmapping.Profile, error)
GetProfileByPlayerID(playerID int) (*dbmapping.Profile, error)
AddPokememe(pokememeData map[string]string, pokememeLocations map[string]string, pokememeElements map[string]string) (int, error)
GetAllPokememes() map[int]*dbmapping.PokememeFull
GetPokememeByID(pokememeID int) (*dbmapping.PokememeFull, error)
GetPokememeByName(name string) (*dbmapping.PokememeFull, error)
DeletePokememeByID(pokememeID int) error
UpdatePokememe(pokememeData map[string]string, pokememeLocations map[string]string, pokememeElements map[string]string) (int, error)
GetElementByID(elementID int) (*datamapping.Element, error)
FindElementIDBySymbol(symbol string) (int, error)
GetLeagueByID(leagueID int) (*datamapping.League, error)
GetLeagueBySymbol(symbol string) (*datamapping.League, error)
GetLevelByID(levelID int) (*datamapping.Level, error)
FindLocationIDByName(name string) (int, error)
GetAllPokememes() map[int]*datamapping.PokememeFull
GetPokememeByID(pokememeID int) (*datamapping.PokememeFull, error)
GetPokememeByName(name string) (*datamapping.PokememeFull, error)
GetPokememesCountByGradeAndLocation(grade int, locationID int) int
GetWeaponTypeByID(weaponID int) (*datamapping.Weapon, error)
GetWeaponTypeByName(name string) (*datamapping.Weapon, error)
}

View File

@@ -44,16 +44,6 @@ func (dc *DataCache) getElements() []datamapping.Element {
return elements
}
func (dc *DataCache) findElementIDBySymbol(symbol string) (int, error) {
for i := range dc.elements {
if dc.elements[i].Symbol == symbol {
return i, nil
}
}
return 0, errors.New("There is no element with symbol = " + symbol)
}
// External functions
// GetElementByID returns element with given ID
@@ -64,3 +54,14 @@ func (dc *DataCache) GetElementByID(elementID int) (*datamapping.Element, error)
return nil, errors.New("There is no element with ID = " + strconv.Itoa(elementID))
}
// FindElementIDBySymbol returns element ID for given symbol
func (dc *DataCache) FindElementIDBySymbol(symbol string) (int, error) {
for i := range dc.elements {
if dc.elements[i].Symbol == symbol {
return i, nil
}
}
return 0, errors.New("There is no element with symbol = " + symbol)
}

View File

@@ -28,12 +28,6 @@ type DataCache struct {
// Note: int in this array for player ID, not for profile ID
currentProfiles map[int]*dbmapping.Profile
currentProfilesMutex sync.Mutex
// Pokememes
pokememes map[int]*dbmapping.Pokememe
pokememesMutex sync.Mutex
// Pokememes with all supported data
fullPokememes map[int]*dbmapping.PokememeFull
fullPokememesMutex sync.Mutex
// Chats
chats map[int]*dbmapping.Chat
@@ -45,13 +39,19 @@ type DataCache struct {
squadPlayers map[int]map[int]*dbmapping.SquadPlayerFull
squadsMutex sync.Mutex
// Non-database data
// Rarely changing data
// Elements
elements map[int]*datamapping.Element
// Leagues
leagues map[int]*datamapping.League
// Levels
levels map[int]*datamapping.Level
// Locations
locations map[int]*datamapping.Location
// Pokememes
pokememes map[int]*datamapping.Pokememe
fullPokememes map[int]*datamapping.PokememeFull
pokememesGradeLocation map[int]map[int]int
// Weapons
weapons map[int]*datamapping.Weapon
}
@@ -75,6 +75,8 @@ func (dc *DataCache) Init() {
dc.loadLocations()
dc.initWeapons()
dc.loadWeapons()
dc.initLevels()
dc.loadLevels()
dc.initPokememes()
dc.loadPokememes()
dc.initPlayers()

56
lib/datacache/levels.go Normal file
View File

@@ -0,0 +1,56 @@
// i2_bot Instinct PokememBro Bot
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
package datacache
import (
"errors"
"gopkg.in/yaml.v2"
"source.wtfteam.pro/i2_bot/i2_bot/lib/datamapping"
"source.wtfteam.pro/i2_bot/i2_bot/static"
"strconv"
)
func (dc *DataCache) initLevels() {
c.Log.Info("Initializing Levels storage...")
dc.levels = make(map[int]*datamapping.Level)
}
func (dc *DataCache) loadLevels() {
c.Log.Info("Load current Levels data to DataCache...")
levels := dc.getLevels()
for i := range levels {
dc.levels[levels[i].ID] = &levels[i]
}
c.Log.Info("Loaded levels in DataCache: " + strconv.Itoa(len(dc.levels)))
}
func (dc *DataCache) getLevels() []datamapping.Level {
levels := []datamapping.Level{}
yamlFile, err := static.ReadFile("levels.yml")
if err != nil {
c.Log.Error(err.Error())
c.Log.Fatal("Can't read levels data file")
}
err = yaml.Unmarshal(yamlFile, &levels)
if err != nil {
c.Log.Error(err.Error())
c.Log.Fatal("Can't parse levels data file")
}
return levels
}
// External functions
// GetLevelByID returns level data by ID
func (dc *DataCache) GetLevelByID(levelID int) (*datamapping.Level, error) {
if dc.levels[levelID] != nil {
return dc.levels[levelID], nil
}
return nil, errors.New("There is no level with ID = " + strconv.Itoa(levelID))
}

View File

@@ -44,7 +44,18 @@ func (dc *DataCache) getLocations() []datamapping.Location {
return locations
}
func (dc *DataCache) findLocationIDByName(name string) (int, error) {
func (dc *DataCache) getLocationByID(locationID int) (*datamapping.Location, error) {
if dc.locations[locationID] != nil {
return dc.locations[locationID], nil
}
return nil, errors.New("There is no localtion with ID = " + strconv.Itoa(locationID))
}
// External functions
// FindLocationIDByName returns location ID for given location name
func (dc *DataCache) FindLocationIDByName(name string) (int, error) {
for i := range dc.locations {
if dc.locations[i].Name == name {
return i, nil

View File

@@ -5,445 +5,133 @@ package datacache
import (
"errors"
"sort"
"gopkg.in/yaml.v2"
"source.wtfteam.pro/i2_bot/i2_bot/lib/datamapping"
"source.wtfteam.pro/i2_bot/i2_bot/lib/dbmapping"
"source.wtfteam.pro/i2_bot/i2_bot/static"
"strconv"
"strings"
"time"
)
func (dc *DataCache) initPokememes() {
c.Log.Info("Initializing Pokememes storage...")
dc.pokememes = make(map[int]*dbmapping.Pokememe)
dc.fullPokememes = make(map[int]*dbmapping.PokememeFull)
dc.pokememes = make(map[int]*datamapping.Pokememe)
dc.fullPokememes = make(map[int]*datamapping.PokememeFull)
dc.pokememesGradeLocation = make(map[int]map[int]int)
}
func (dc *DataCache) loadPokememes() {
c.Log.Info("Load current Pokememes data from database to DataCache...")
pokememes := []dbmapping.Pokememe{}
err := c.Db.Select(&pokememes, "SELECT * FROM pokememes WHERE is_active=1")
if err != nil {
// This is critical error and we need to stop immediately!
c.Log.Fatal(err.Error())
}
pokememesElements := []dbmapping.PokememeElement{}
err = c.Db.Select(&pokememesElements, "SELECT * FROM pokememes_elements")
if err != nil {
// This is critical error and we need to stop immediately!
c.Log.Fatal(err)
}
pokememesLocations := []dbmapping.PokememeLocation{}
err = c.Db.Select(&pokememesLocations, "SELECT * FROM pokememes_locations")
if err != nil {
// This is critical error and we need to stop immediately!
c.Log.Fatal(err)
}
c.Log.Info("Load current Pokememes data to DataCache...")
pokememes := dc.getPokememes()
dc.pokememesMutex.Lock()
dc.fullPokememesMutex.Lock()
for i := range pokememes {
c.Log.Debug("Loading pokememe with name: " + pokememes[i].Name)
dc.pokememes[pokememes[i].ID] = &pokememes[i]
// Filling fullPokememes
fullPokememe := dbmapping.PokememeFull{}
elementsListed := []datamapping.Element{}
locationsListed := []datamapping.Location{}
for j := range pokememesLocations {
if pokememesLocations[j].PokememeID == pokememes[i].ID {
for l := range dc.locations {
if pokememesLocations[j].LocationID == dc.locations[l].ID {
locationsListed = append(locationsListed, *dc.locations[l])
}
}
}
if dc.pokememesGradeLocation[pokememes[i].Grade] == nil {
dc.pokememesGradeLocation[pokememes[i].Grade] = make(map[int]int)
}
for k := range pokememesElements {
if pokememesElements[k].PokememeID == pokememes[i].ID {
for e := range dc.elements {
if pokememesElements[k].ElementID == dc.elements[e].ID {
elementsListed = append(elementsListed, *dc.elements[e])
}
}
pokememeFull := datamapping.PokememeFull{}
pokememeFullElements := []datamapping.Element{}
pokememeFullLocations := []datamapping.Location{}
pokememeFull.Pokememe = pokememes[i]
for ii := range pokememes[i].Elements {
element, err := dc.GetElementByID(pokememes[i].Elements[ii])
if err != nil {
// This is critical
c.Log.Fatal(err.Error())
}
pokememeFullElements = append(pokememeFullElements, *element)
}
for ii := range pokememes[i].Locations {
location, err := dc.getLocationByID(pokememes[i].Locations[ii])
if err != nil {
// This is critical
c.Log.Fatal(err.Error())
}
pokememeFullLocations = append(pokememeFullLocations, *location)
dc.pokememesGradeLocation[pokememes[i].Grade][location.ID]++
}
fullPokememe.Pokememe = pokememes[i]
fullPokememe.Elements = elementsListed
fullPokememe.Locations = locationsListed
dc.fullPokememes[pokememes[i].ID] = &fullPokememe
pokememeFull.Elements = pokememeFullElements
pokememeFull.Locations = pokememeFullLocations
dc.fullPokememes[pokememes[i].ID] = &pokememeFull
}
c.Log.Info("Loaded pokememes with all additional information in DataCache: " + strconv.Itoa(len(dc.fullPokememes)))
dc.pokememesMutex.Unlock()
dc.fullPokememesMutex.Unlock()
c.Log.Info("Loaded pokememes in DataCache: " + strconv.Itoa(len(dc.fullPokememes)))
}
func (dc *DataCache) getPokememes() []datamapping.Pokememe {
pokememes := []datamapping.Pokememe{}
allPokememesFiles, err := static.WalkDirs("pokememes", false)
if err != nil {
c.Log.Error(err.Error())
c.Log.Fatal("Can't read directory with pokememes information")
}
var pokememesData []byte
for i := range allPokememesFiles {
yamlFile, err := static.ReadFile(allPokememesFiles[i])
if err != nil {
c.Log.Error(err.Error())
c.Log.Fatal("Can't read pokememes data file: " + allPokememesFiles[i])
}
for ii := range yamlFile {
pokememesData = append(pokememesData, yamlFile[ii])
}
pokememesData = append(pokememesData, '\n')
}
err = yaml.Unmarshal(pokememesData, &pokememes)
if err != nil {
c.Log.Error(err.Error())
c.Log.Fatal("Can't parse merged pokememes data")
}
return pokememes
}
// External functions
// AddPokememe adds pokememe from parser
func (dc *DataCache) AddPokememe(pokememeData map[string]string, pokememeLocations map[string]string, pokememeElements map[string]string) (int, error) {
_, noerr := dc.GetPokememeByName(pokememeData["name"])
if noerr == nil {
return 0, errors.New("This pokememe already exists")
}
gradeInt := c.Statistics.GetPoints(pokememeData["grade"])
attackInt := c.Statistics.GetPoints(pokememeData["attack"])
hpInt := c.Statistics.GetPoints(pokememeData["hp"])
mpInt := c.Statistics.GetPoints(pokememeData["mp"])
defenceInt := attackInt
if pokememeData["defence"] != "" {
defenceInt = c.Statistics.GetPoints(pokememeData["defence"])
}
priceInt := c.Statistics.GetPoints(pokememeData["price"])
creatorID := c.Statistics.GetPoints(pokememeData["creator_id"])
if !(gradeInt != 0 && attackInt != 0 && hpInt != 0 && mpInt != 0 && defenceInt != 0 && priceInt != 0 && creatorID != 0) {
return 0, errors.New("Some of the required numerical values are empty")
}
pokememe := dbmapping.Pokememe{}
pokememe.Grade = gradeInt
pokememe.Name = pokememeData["name"]
pokememe.Description = pokememeData["description"]
pokememe.Attack = attackInt
pokememe.HP = hpInt
pokememe.MP = mpInt
pokememe.Defence = defenceInt
pokememe.Price = priceInt
if pokememeData["purchaseable"] == "true" {
pokememe.Purchaseable = true
} else {
pokememe.Purchaseable = false
}
pokememe.ImageURL = pokememeData["image"]
pokememe.PlayerID = creatorID
pokememe.IsActive = 1
pokememe.CreatedAt = time.Now().UTC()
locations := []datamapping.Location{}
elements := []datamapping.Element{}
for i := range pokememeLocations {
locationID, err := dc.findLocationIDByName(pokememeLocations[i])
if err != nil {
return 0, err
}
locations = append(locations, *dc.locations[locationID])
}
for i := range pokememeElements {
elementID, err := dc.findElementIDBySymbol(pokememeElements[i])
if err != nil {
return 0, err
}
elements = append(elements, *dc.elements[elementID])
}
// All objects are prepared, let's fill database with it!
c.Log.Debug("Filling pokememe...")
_, err := c.Db.NamedExec("INSERT INTO pokememes VALUES(NULL, :grade, :name, :description, :attack, :hp, :mp, :defence, :price, :purchaseable, :image_url, :player_id, :is_active, :created_at)", &pokememe)
if err != nil {
return 0, err
}
c.Log.Debug("Finding newly added pokememe...")
insertedPokememe := dbmapping.Pokememe{}
err = c.Db.Get(&insertedPokememe, c.Db.Rebind("SELECT * FROM pokememes WHERE grade=? AND name=?"), pokememe.Grade, pokememe.Name)
if err != nil {
c.Log.Debug("Can't find newly added pokememe!")
return 0, err
}
// Now we creating locations and elements links
locationsAndElementsFilledSuccessfully := true
c.Log.Debug("Filling locations...")
for i := range locations {
link := dbmapping.PokememeLocation{}
link.PokememeID = insertedPokememe.ID
link.LocationID = locations[i].ID
link.CreatedAt = time.Now().UTC()
_, err := c.Db.NamedExec("INSERT INTO pokememes_locations VALUES(NULL, :pokememe_id, :location_id, :created_at)", &link)
if err != nil {
c.Log.Error(err.Error())
locationsAndElementsFilledSuccessfully = false
}
}
c.Log.Debug("Filling elements...")
for i := range elements {
link := dbmapping.PokememeElement{}
link.PokememeID = insertedPokememe.ID
link.ElementID = elements[i].ID
link.CreatedAt = time.Now().UTC()
_, err := c.Db.NamedExec("INSERT INTO pokememes_elements VALUES(NULL, :pokememe_id, :element_id, :created_at)", &link)
if err != nil {
c.Log.Error(err.Error())
locationsAndElementsFilledSuccessfully = false
}
}
if !locationsAndElementsFilledSuccessfully {
c.Log.Debug("All fucked up, removing what we have already added...")
// There is something fucked up. In normal state we're should never reach this code
_, err = c.Db.NamedExec("DELETE FROM pokememes_locations WHERE pokememe_id=:id", &insertedPokememe)
if err != nil {
c.Log.Error(err.Error())
}
_, err = c.Db.NamedExec("DELETE FROM pokememes_elements WHERE pokememe_id=:id", &insertedPokememe)
if err != nil {
c.Log.Error(err.Error())
}
_, err = c.Db.NamedExec("DELETE FROM pokememes where id=:id", &insertedPokememe)
if err != nil {
c.Log.Error(err.Error())
}
return 0, errors.New("Failed to add pokememe to database")
}
fullPokememe := dbmapping.PokememeFull{}
fullPokememe.Pokememe = insertedPokememe
fullPokememe.Locations = locations
fullPokememe.Elements = elements
// Filling data cache
dc.pokememesMutex.Lock()
dc.fullPokememesMutex.Lock()
dc.pokememes[insertedPokememe.ID] = &insertedPokememe
dc.fullPokememes[insertedPokememe.ID] = &fullPokememe
dc.pokememesMutex.Unlock()
dc.fullPokememesMutex.Unlock()
return insertedPokememe.ID, nil
}
// GetAllPokememes returns all pokememes
// Index in resulted map counts all pokememes ordered by grade and alphabetically
func (dc *DataCache) GetAllPokememes() map[int]*dbmapping.PokememeFull {
pokememes := make(map[int]*dbmapping.PokememeFull)
dc.fullPokememesMutex.Lock()
func (dc *DataCache) GetAllPokememes() map[int]*datamapping.PokememeFull {
pokememes := make(map[int]*datamapping.PokememeFull)
var keys []string
keysToIDs := make(map[string]int)
for i := range dc.fullPokememes {
gradeKey := ""
if dc.fullPokememes[i].Pokememe.Grade == 0 {
gradeKey += "Z"
} else {
gradeKey += string(rune('A' - 1 + dc.fullPokememes[i].Pokememe.Grade))
}
keys = append(keys, gradeKey+"_"+strconv.Itoa(dc.fullPokememes[i].Pokememe.Attack+100000000000000)+"_"+dc.fullPokememes[i].Pokememe.Name)
keysToIDs[gradeKey+"_"+strconv.Itoa(dc.fullPokememes[i].Pokememe.Attack+100000000000000)+"_"+dc.fullPokememes[i].Pokememe.Name] = i
}
sort.Strings(keys)
idx := 0
for _, k := range keys {
pokememes[idx] = dc.fullPokememes[keysToIDs[k]]
idx++
pokememes[dc.fullPokememes[i].Pokememe.ID] = dc.fullPokememes[i]
}
dc.fullPokememesMutex.Unlock()
return pokememes
}
// GetPokememeByID returns pokememe with additional information by ID
func (dc *DataCache) GetPokememeByID(pokememeID int) (*dbmapping.PokememeFull, error) {
dc.fullPokememesMutex.Lock()
func (dc *DataCache) GetPokememeByID(pokememeID int) (*datamapping.PokememeFull, error) {
if dc.fullPokememes[pokememeID] != nil {
dc.fullPokememesMutex.Unlock()
return dc.fullPokememes[pokememeID], nil
}
dc.fullPokememesMutex.Unlock()
return nil, errors.New("There is no pokememe with ID = " + strconv.Itoa(pokememeID))
}
// GetPokememeByName returns pokememe from datacache by name
func (dc *DataCache) GetPokememeByName(name string) (*dbmapping.PokememeFull, error) {
dc.fullPokememesMutex.Lock()
// GetPokememeByName returns pokememe with additional information by name
func (dc *DataCache) GetPokememeByName(pokememeName string) (*datamapping.PokememeFull, error) {
for i := range dc.fullPokememes {
if strings.HasPrefix(dc.fullPokememes[i].Pokememe.Name, name) {
dc.fullPokememesMutex.Unlock()
if strings.Contains(dc.fullPokememes[i].Pokememe.Name, pokememeName) {
return dc.fullPokememes[i], nil
}
}
dc.fullPokememesMutex.Unlock()
return nil, errors.New("There is no pokememe with name = " + name)
return nil, errors.New("There is no pokememe with name = " + pokememeName)
}
// DeletePokememeByID removes pokememe from database
func (dc *DataCache) DeletePokememeByID(pokememeID int) error {
pokememe, err := dc.GetPokememeByID(pokememeID)
if err != nil {
return err
// GetPokememesCountByGradeAndLocation returns pokememes count with given grade on given location
func (dc *DataCache) GetPokememesCountByGradeAndLocation(grade int, locationID int) int {
if dc.pokememesGradeLocation[grade] == nil {
return 0
}
_, err = c.Db.NamedExec("DELETE FROM pokememes_locations WHERE pokememe_id=:id", &pokememe.Pokememe)
if err != nil {
c.Log.Error(err.Error())
}
_, err = c.Db.NamedExec("DELETE FROM pokememes_elements WHERE pokememe_id=:id", &pokememe.Pokememe)
if err != nil {
c.Log.Error(err.Error())
}
_, err = c.Db.NamedExec("DELETE FROM pokememes where id=:id", &pokememe.Pokememe)
if err != nil {
c.Log.Error(err.Error())
}
dc.pokememesMutex.Lock()
dc.fullPokememesMutex.Lock()
delete(dc.pokememes, pokememe.Pokememe.ID)
delete(dc.fullPokememes, pokememe.Pokememe.ID)
dc.pokememesMutex.Unlock()
dc.fullPokememesMutex.Unlock()
return nil
}
// UpdatePokememe updates existing pokememes in database and datacache
func (dc *DataCache) UpdatePokememe(pokememeData map[string]string, pokememeLocations map[string]string, pokememeElements map[string]string) (int, error) {
knownPokememe, err := dc.GetPokememeByName(pokememeData["name"])
if err != nil {
// This should never happen, but who knows?
return 0, errors.New("This pokememe doesn't exist. We should add it instead")
}
gradeInt := c.Statistics.GetPoints(pokememeData["grade"])
attackInt := c.Statistics.GetPoints(pokememeData["attack"])
hpInt := c.Statistics.GetPoints(pokememeData["hp"])
mpInt := c.Statistics.GetPoints(pokememeData["mp"])
defenceInt := attackInt
if pokememeData["defence"] != "" {
defenceInt = c.Statistics.GetPoints(pokememeData["defence"])
}
priceInt := c.Statistics.GetPoints(pokememeData["price"])
creatorID := c.Statistics.GetPoints(pokememeData["creator_id"])
if !(gradeInt != 0 && attackInt != 0 && hpInt != 0 && mpInt != 0 && defenceInt != 0 && priceInt != 0 && creatorID != 0) {
return 0, errors.New("Some of the required numerical values are empty")
}
pokememe := knownPokememe.Pokememe
pokememe.Grade = gradeInt
pokememe.Name = pokememeData["name"]
pokememe.Description = pokememeData["description"]
pokememe.Attack = attackInt
pokememe.HP = hpInt
pokememe.MP = mpInt
pokememe.Defence = defenceInt
pokememe.Price = priceInt
if pokememeData["purchaseable"] == "true" {
pokememe.Purchaseable = true
} else {
pokememe.Purchaseable = false
}
pokememe.ImageURL = pokememeData["image"]
pokememe.PlayerID = creatorID
pokememe.CreatedAt = time.Now().UTC()
locations := []datamapping.Location{}
elements := []datamapping.Element{}
for i := range pokememeLocations {
locationID, err := dc.findLocationIDByName(pokememeLocations[i])
if err != nil {
return 0, err
}
locations = append(locations, *dc.locations[locationID])
}
for i := range pokememeElements {
elementID, err := dc.findElementIDBySymbol(pokememeElements[i])
if err != nil {
return 0, err
}
elements = append(elements, *dc.elements[elementID])
}
// All objects are prepared, let's fill database with it!
c.Log.Debug("Updating existing pokememe...")
_, err = c.Db.NamedExec("UPDATE pokememes SET grade=:grade, name=:name, description=:description, attack=:attack, hp=:hp, mp=:mp, defence=:defence, price=:price, purchaseable=:purchaseable, image_url=:image_url, player_id=:player_id, created_at=:created_at WHERE id=:id", &pokememe)
if err != nil {
return 0, err
}
// Now we creating locations and elements links
locationsAndElementsFilledSuccessfully := true
c.Log.Debug("Destroying old relations...")
_, err = c.Db.NamedExec("DELETE FROM pokememes_locations WHERE pokememe_id=:id", &pokememe)
if err != nil {
c.Log.Error(err.Error())
locationsAndElementsFilledSuccessfully = false
}
_, err = c.Db.NamedExec("DELETE FROM pokememes_elements WHERE pokememe_id=:id", &pokememe)
if err != nil {
c.Log.Error(err.Error())
locationsAndElementsFilledSuccessfully = false
}
c.Log.Debug("Filling locations...")
for i := range locations {
link := dbmapping.PokememeLocation{}
link.PokememeID = pokememe.ID
link.LocationID = locations[i].ID
link.CreatedAt = time.Now().UTC()
_, err := c.Db.NamedExec("INSERT INTO pokememes_locations VALUES(NULL, :pokememe_id, :location_id, :created_at)", &link)
if err != nil {
c.Log.Error(err.Error())
locationsAndElementsFilledSuccessfully = false
}
}
c.Log.Debug("Filling elements...")
for i := range elements {
link := dbmapping.PokememeElement{}
link.PokememeID = pokememe.ID
link.ElementID = elements[i].ID
link.CreatedAt = time.Now().UTC()
_, err := c.Db.NamedExec("INSERT INTO pokememes_elements VALUES(NULL, :pokememe_id, :element_id, :created_at)", &link)
if err != nil {
c.Log.Error(err.Error())
locationsAndElementsFilledSuccessfully = false
}
}
if !locationsAndElementsFilledSuccessfully {
c.Log.Debug("All fucked up, removing what we have already added...")
// There is something fucked up. In normal state we're should never reach this code
_, err = c.Db.NamedExec("DELETE FROM pokememes_locations WHERE pokememe_id=:id", &pokememe)
if err != nil {
c.Log.Error(err.Error())
}
_, err = c.Db.NamedExec("DELETE FROM pokememes_elements WHERE pokememe_id=:id", &pokememe)
if err != nil {
c.Log.Error(err.Error())
}
_, err = c.Db.NamedExec("DELETE FROM pokememes where id=:id", &pokememe)
if err != nil {
c.Log.Error(err.Error())
}
return 0, errors.New("Failed to add pokememe to database")
}
fullPokememe := dbmapping.PokememeFull{}
fullPokememe.Pokememe = pokememe
fullPokememe.Locations = locations
fullPokememe.Elements = elements
// Filling data cache
dc.pokememesMutex.Lock()
dc.fullPokememesMutex.Lock()
dc.pokememes[pokememe.ID] = &pokememe
dc.fullPokememes[pokememe.ID] = &fullPokememe
dc.pokememesMutex.Unlock()
dc.fullPokememesMutex.Unlock()
return pokememe.ID, nil
return dc.pokememesGradeLocation[grade][locationID]
}