Welcome to the Achaea Forums! Please be sure to read the Forum Rules.

ShopKeeper

RangorRangor Posts: 3,068Member @@ - Legendary Achaean
Hi,

I've recently taken on a shop in Eleusis and looking for scripts to make it easier. I've got one now that helps with the pricing of items, which is great. Now I'm looking for one to help me see what's actually been sold or is missing from the store.. So what I'm looking for is something like...

I do "checkstore", and the script goes wares, adds everything in the store to a database.
The next time I do "checksales", it goes wares again, and then in a neat format displays what's now missing or has been added.
When I'm done restocking I'll do "checkstore" again to update the database.

If no one has anything like that I'd be interested in paying someone 50 credits to make it for me!
image
«1

Comments

  • TreyTrey Posts: 4,631Member @@ - Legendary Achaean
    I actually wouldn't mind something like this, but it would have to be for Nexus or zMUD.

  • MelainaMelaina Posts: 42Member ✭✭✭ - Distinguished
    I'm surprised Achaea hasn't just done what MKO did and created Shoplog which told you what has sold and for how much.
    Melaina Naftis - Spectral Arbiter of the Krymenian Academy
    KayeilOceanaAldwicTysandr
  • AntoniusAntonius Posts: 4,500Member @@ - Legendary Achaean
    Melaina said:
    I'm surprised Achaea hasn't just done what MKO did and created Shoplog which told you what has sold and for how much.
    People have asked for it. Frequently. I'm sure you'll probably find a number of threads in the Golden Dais section specifically about it.

    However, development resources are limited, so they can't do everything; saying "hasn't just done" completely ignores how much work this would actually be, and what else doesn't get done as a result of doing it. Things are rarely simple when you're talking about complicated - and, in Achaea's case, often very old - systems.
  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    I guess I must learn databases and use gmcp info to do this for me.
    image
  • AntoniusAntonius Posts: 4,500Member @@ - Legendary Achaean
    You don't need databases. Not even sure it would make it easier if you did use one.
  • CaelanCaelan Posts: 1,112Member ✭✭✭✭✭ - Grand Achaean
    I have been tempted to make a script like this for the longest time (since I ran shops in Shallam).  Just never have time.

  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    edited May 2017
    Can you save the data in tables when you close mudlet?
    image
  • AntoniusAntonius Posts: 4,500Member @@ - Legendary Achaean
    @Rangor Look into table.save and table.load. You'll want to set up event handlers for the sysExitEvent to save and sysLoadEvent to load.
    Kogan
  • AhmetAhmet Wherever I wanna bePosts: 3,370Member @@ - Legendary Achaean
    You can save tables, yes, but I'd recommend databases in case of crash.

    Though, for this script, you can just save the tables when you use the shopcheck alias or whatever it is, so that won't be an issue.
    Huh. Neat.
    Rangor
  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    Ty. Should be fairly easy with the gmcp inventory lists then.
    image
  • JonathinJonathin Retirement hole.Posts: 3,289Member @@ - Legendary Achaean
    I might have a crack at this later.

    My site will remain up, but will not be maintained. The repository will continue to have scripts added to it if I decide to play another game. Maybe I'll see you around in Starmourn!
    Tutorials and scripts  The Repository

  • KoganKogan Posts: 401Member ✭✭✭✭ - Eminent
    Antonius said:
    @Rangor Look into table.save and table.load. You'll want to set up event handlers for the sysExitEvent to save and sysLoadEvent to load.
    Ive thought about creating something similar as well, but am terrible with gmcp when it comes to items and how list and what not work. However you could definitely use these events, but I just table.load on login trigger and save within functions used to update information in the table at the end of it.
  • SkyeSkye The Duchess BellaterePosts: 2,723Member, Seafaring Liason @@ - Legendary Achaean
    Jarrod actually threw together something for carts during the crafter's fair a few years back. One thing that I find important functionally is that checking your shop wares shouldn't override the original list of stock.

    I check my shop stock every day but I only restock after a certain amount of items has sold because this allows me to take inventory and refresh stock more easily. Stockroom space is very limited, so I cycle items sold to make things look fresh.

    To this end, I keep pretty extensive spreadsheets haha. I could do better with them, but haven't really had the time.


  • KayeilKayeil Washington StatePosts: 2,800Member @@ - Legendary Achaean
    Caelan said:
    Skye said:
    Jarrod actually threw together something for carts during the crafter's fair a few years back. One thing that I find important functionally is that checking your shop wares shouldn't override the original list of stock.

    I check my shop stock every day but I only restock after a certain amount of items has sold because this allows me to take inventory and refresh stock more easily. Stockroom space is very limited, so I cycle items sold to make things look fresh.

    To this end, I keep pretty extensive spreadsheets haha. I could do better with them, but haven't really had the time.
    I did the spreadsheet thing for a while.  Then I said to myself, I says, "Self!, this is dumb. It's a game"

    And @Skye I don't know if you know this,  but I secretly LOVE your marketing messages.  The salesmanship and humor is unparalleled. Even though I haven't bought food in ..well, since mutton.. I absolutely love the thought of you wandering the streets like the Peanut guy at a ballpark, hawking your wares.  (totally serious)
    She really does have top notch marketing and her shops are really awesome. You can tell she puts a lot of effort into every little thing from the wares to how she cycles them so it's like there's always something new to see or try out.
    What doesn't kill you gives you exp.

    Utianima
  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    @Kipposhi claims the bounty.


    function asInventoryList(gmcpItems) local tableResult = {}
    for _, item in ipairs(gmcpItems) do local listItem = tableResult[item.name] if not listItem then tableResult[item.name] = 0 end
    tableResult[item.name] = tableResult[item.name] + 1 end
    return tableResult end
    function updateInventory() inventoryList = asInventoryList(gmcp.Char.Items.List.items) end
    function compareInventory() tempinventoryList = asInventoryList(gmcp.Char.Items.List.items)
    missingItems = {}
    for name, count in pairs(inventoryList) do if not tempinventoryList[name] or tempinventoryList[name] < count then local currentCount = tempinventoryList[name] or 0 table.insert(missingItems, { name = name, diff = count - currentCount }) end end
    for _, v in ipairs(missingItems) do cecho("\n<green>Item: " ..v.name.. " - <blue>Sold: " ..v.diff) end end

    image
    Cailin
  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    edited June 2017
    updated.... 

    Run updateInventory() when you're saving your normal stocking levels.

    run compareInventory() when you want to see what's missing since you ran updateInventory()
    inventoryList = {}


    function asInventoryList(gmcpItems)

    local tableResult = {}


    for _, item in ipairs(gmcpItems) do

    local listItem = tableResult[item.name]

    if not listItem then

    tableResult[item.name] = 0

    end


    tableResult[item.name] = tableResult[item.name] + 1

    end


    return tableResult

    end


    function updateInventory()

    inventoryList = asInventoryList(gmcp.Char.Items.List.items)


    saveInventory()


    end


    function saveInventory()

    if string.char(getMudletHomeDir():byte()) == "/"

    then _sep = "/"

    else _sep = "\\"

    end -- if

    shop_inventory = getMudletHomeDir() .. _sep .. "shop_inventory.lua"

    table.save(shop_inventory, inventoryList)


    end -- func


    function loadInventory()

    if string.char(getMudletHomeDir():byte()) == "/"

    then _sep = "/"

    else _sep = "\\"

    end -- if

    shop_inventory = getMudletHomeDir() .. _sep .. "shop_inventory.lua"

    if (io.exists(shop_inventory)) then

    table.load(shop_inventory, inventoryList)

    end -- if

    end -- func


    function compareInventory()

    tempinventoryList = asInventoryList(gmcp.Char.Items.List.items)

    loadInventory()

    missingItems = {}


    for name, count in pairs(inventoryList) do

    if not tempinventoryList[name] or tempinventoryList[name] < count then

    local currentCount = tempinventoryList[name] or 0

    table.insert(missingItems, { name = name, diff = count - currentCount })

    end

    end


    for _, v in ipairs(missingItems) do

    cecho("\n<green>Item: " ..v.name.. " - <blue>Sold: " ..v.diff)

    end

    end


    image
  • KayeilKayeil Washington StatePosts: 2,800Member @@ - Legendary Achaean
    edited June 2017
    Thank you @Rangor and @Kipposhi for sharing! I do all of my shopkeeping manually since I can't code and this makes up for the lack of a shop log greatly and saves me some time from going through the list myself every day. I really appreciate the time you're saving me!

    Edit: My only suggestion if this is ever updated again is if it can me made to monitor multiple shops instead of one. I spoke to @Kogan and he told me he could do it with what's there if I needed him to (not sure yet), but I think that'd be highly beneficial for Chancellors who run multiple city shops.
    What doesn't kill you gives you exp.

  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    If you have more than one shop, you can copy paste it and rename everywhere it says "inventory" to shopname_inventory and you'll have one script for each shop
    image
    Kayeil
  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    Kayeil said:
    Thank you @Rangor and @Kipposhi for sharing! I do all of my shopkeeping manually since I can't code and this makes up for the lack of a shop log greatly and saves me some time from going through the list myself every day. I really appreciate the time you're saving me!

    Edit: My only suggestion if this is ever updated again is if it can me made to monitor multiple shops instead of one. I spoke to @Kogan and he told me he could do it with what's there if I needed him to (not sure yet), but I think that'd be highly beneficial for Chancellors who run multiple city shops.
    Multiple cityshops, what a luxury.
    image
    Caelan
  • AntoniusAntonius Posts: 4,500Member @@ - Legendary Achaean
    Rangor said:
    If you have more than one shop, you can copy paste it and rename everywhere it says "inventory" to shopname_inventory and you'll have one script for each shop

    You could do that, but there's no real need. It's just a change to a few lines of code to get it to support multiple shops, just by making "inventoryList" a dictionary using room number as the key, rather than a list for just a single room's worth of items. Hopefully @Kipposhi doesn't mind me making some tweaks to his stuff. If you've already got an inventory list saved, you'll probably want to go and update it after updating the script.

    inventoryList = {}
    
    function asInventoryList(gmcpItems)
    	local tableResult = {}
    
    	for _, item in ipairs(gmcpItems) do
    		local listItem = tableResult[item.name]
    		
    		if not listItem then
    			tableResult[item.name] = 0
    		end
    
    		tableResult[item.name] = tableResult[item.name] + 1
    	end
    
    	return tableResult
    end
    
    function updateInventory()
    	inventoryList[gmcp.Room.Info.num] = asInventoryList(gmcp.Char.Items.List.items)
    
    	saveInventory()
    end
    
    function saveInventory()
    	if string.char(getMudletHomeDir():byte()) == "/" then 
    		_sep = "/"
    	else 
    		_sep = "\\"
    	end -- if
    
    	shop_inventory = getMudletHomeDir() .. _sep .. "shop_inventory.lua"
    
    	table.save(shop_inventory, inventoryList)
    end -- func
    
    function loadInventory()
    	if string.char(getMudletHomeDir():byte()) == "/" then 
    		_sep = "/"
    	else 
    		_sep = "\\"
    	end -- if
    
    	shop_inventory = getMudletHomeDir() .. _sep .. "shop_inventory.lua"
    
    	if (io.exists(shop_inventory)) then
    		table.load(shop_inventory, inventoryList)
    	end -- if
    end -- func
    registerAnonymousEventHandler("sysLoadEvent", "loadInventory")
    
    function compareInventory()
    	tempinventoryList = asInventoryList(gmcp.Char.Items.List.items)
    
    	loadInventory()
    
    	missingItems = {}
    
    	for name, count in pairs(inventoryList[gmcp.Room.Info.num]) do
    		if not tempinventoryList[name] or tempinventoryList[name] < count then
    			local currentCount = tempinventoryList[name] or 0
    
    			table.insert(missingItems, { name = name, diff = count - currentCount })
    		end
    	end
    
    	for _, v in ipairs(missingItems) do
    		cecho("\nItem: " ..v.name.. " - Sold: " ..v.diff)
    	end
    end
    
    RangorKayeilKoganKyrra
  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    Antonius said:
    Rangor said:
    If you have more than one shop, you can copy paste it and rename everywhere it says "inventory" to shopname_inventory and you'll have one script for each shop

    You could do that, but there's no real need. It's just a change to a few lines of code to get it to support multiple shops, just by making "inventoryList" a dictionary using room number as the key, rather than a list for just a single room's worth of items. Hopefully @Kipposhi doesn't mind me making some tweaks to his stuff. If you've already got an inventory list saved, you'll probably want to go and update it after updating the script.

    inventoryList = {}
    
    function asInventoryList(gmcpItems)
    	local tableResult = {}
    
    	for _, item in ipairs(gmcpItems) do
    		local listItem = tableResult[item.name]
    		
    		if not listItem then
    			tableResult[item.name] = 0
    		end
    
    		tableResult[item.name] = tableResult[item.name] + 1
    	end
    
    	return tableResult
    end
    
    function updateInventory()
    	inventoryList[gmcp.Room.Info.num] = asInventoryList(gmcp.Char.Items.List.items)
    
    	saveInventory()
    end
    
    function saveInventory()
    	if string.char(getMudletHomeDir():byte()) == "/" then 
    		_sep = "/"
    	else 
    		_sep = "\\"
    	end -- if
    
    	shop_inventory = getMudletHomeDir() .. _sep .. "shop_inventory.lua"
    
    	table.save(shop_inventory, inventoryList)
    end -- func
    
    function loadInventory()
    	if string.char(getMudletHomeDir():byte()) == "/" then 
    		_sep = "/"
    	else 
    		_sep = "\\"
    	end -- if
    
    	shop_inventory = getMudletHomeDir() .. _sep .. "shop_inventory.lua"
    
    	if (io.exists(shop_inventory)) then
    		table.load(shop_inventory, inventoryList)
    	end -- if
    end -- func
    registerAnonymousEventHandler("sysLoadEvent", "loadInventory")
    
    function compareInventory()
    	tempinventoryList = asInventoryList(gmcp.Char.Items.List.items)
    
    	loadInventory()
    
    	missingItems = {}
    
    	for name, count in pairs(inventoryList[gmcp.Room.Info.num]) do
    		if not tempinventoryList[name] or tempinventoryList[name] < count then
    			local currentCount = tempinventoryList[name] or 0
    
    			table.insert(missingItems, { name = name, diff = count - currentCount })
    		end
    	end
    
    	for _, v in ipairs(missingItems) do
    		cecho("\nItem: " ..v.name.. " - Sold: " ..v.diff)
    	end
    end
    
    oo, clever. I mostly contributed with the cecho, all the fors and pairs and ipairs confuse the blip out of me. especially what the asInventoryList does. :)
    image
  • KayeilKayeil Washington StatePosts: 2,800Member @@ - Legendary Achaean
    Rangor said:
    Kayeil said:
    Thank you @Rangor and @Kipposhi for sharing! I do all of my shopkeeping manually since I can't code and this makes up for the lack of a shop log greatly and saves me some time from going through the list myself every day. I really appreciate the time you're saving me!

    Edit: My only suggestion if this is ever updated again is if it can me made to monitor multiple shops instead of one. I spoke to @Kogan and he told me he could do it with what's there if I needed him to (not sure yet), but I think that'd be highly beneficial for Chancellors who run multiple city shops.
    Multiple cityshops, what a luxury.
    Indeed! I don't know how it works in other cities but I know Cyrene's Chancellor runs more than one for the city. I think Targossas has several org shops as well? Including one in Cyrene that's run by one of their Houses, I think (Luminai?). Thanks for the updates guys!
    What doesn't kill you gives you exp.

  • KipposhiKipposhi Posts: 1Member
    I don't forums much, but if you need any more help send me a message IG or something.
    Kogan
  • MerewynMerewyn Posts: 5Member
    can someone break this down for the completely code-illiterate me? Am I meant to just c/p all this into a single script, then create aliases that call on these functions? 
  • RangorRangor Posts: 3,068Member @@ - Legendary Achaean
    Merewyn said:
    can someone break this down for the completely code-illiterate me? Am I meant to just c/p all this into a single script, then create aliases that call on these functions? 
    Yep!
    image
  • KlendathuKlendathu Eye of the StormPosts: 2,922Member @@ - Legendary Achaean
    Tysandyr, I need to send you a project i've got for work, about 10k rows of VBA code in a spreadsheet, needs commenting. Thanks,

    Tharos, the Announcer of Delos shouts, "It's near the end of the egghunt and I still haven't figured out how to pronounce Clean-dat-hoo."
    TysandrRangorCaelan
  • TysandrTysandr Posts: 436Member ✭✭✭✭ - Eminent
    1: codecodecodecode  'R
    2: codecodecodecode  '2
    3: codecodecodecode  'D
    4: codecodecodecode  '2
    5: codecodecodecode  'R
    6: codecodecodecode  '2

    I got you bae
    Nexus: Accents, Autotriggers, Dragon Talismans
    "As the child did... without the rope. Then fear will find you again."

    Caelan
«1
Sign In to Comment.