Initial Release of IGNCore version 2.5
This commit is contained in:
@@ -0,0 +1,342 @@
|
||||
import re
|
||||
import time
|
||||
|
||||
from core.chat_blob import ChatBlob
|
||||
from core.db import DB
|
||||
from core.registry import Registry
|
||||
from core.sender_obj import SenderObj
|
||||
from core.text import Text
|
||||
from modules.core.accounting.services.account_service import AccountService
|
||||
from modules.raidbot.raid.raidbot_controller import Raider
|
||||
|
||||
|
||||
class AuctionBid:
|
||||
def __init__(self, sender: SenderObj, account, current_amount, max_amount):
|
||||
self.sender = sender
|
||||
self.account = account
|
||||
self.current_amount = current_amount
|
||||
self.max_amount = max_amount
|
||||
|
||||
def __str__(self):
|
||||
return self.__dict__.__str__()
|
||||
|
||||
|
||||
class AuctionStrategy:
|
||||
def __init__(self):
|
||||
self.bot = Registry.get_instance("bot")
|
||||
self.db: DB = Registry.get_instance("db")
|
||||
self.text: Text = Registry.get_instance("text")
|
||||
self.account_service: AccountService = Registry.get_instance("account_service")
|
||||
self.job_scheduler = Registry.get_instance("job_scheduler")
|
||||
self.raid_controller = None
|
||||
self.raid_controller = Registry.get_instance("raidbot_controller", is_optional=True)
|
||||
self.auction_start_time = None
|
||||
self.auction_end_time = None
|
||||
self.announce_interval = None
|
||||
self.is_started = False
|
||||
self.items = dict()
|
||||
self.winning_bids = dict()
|
||||
self.next_item_index = 1
|
||||
# noinspection PyTypeChecker
|
||||
self.auctioneer: SenderObj = None
|
||||
self.job_id = None
|
||||
self.is_running = False
|
||||
|
||||
def start(self, sender: SenderObj, duration, announce_interval):
|
||||
if not self.items:
|
||||
return "Could not find any items to start auction."
|
||||
|
||||
self.is_started = True
|
||||
self.auction_start_time = int(time.time())
|
||||
self.auctioneer = sender
|
||||
self.auction_end_time = self.auction_start_time + duration
|
||||
self.is_running = True
|
||||
self.announce_interval = announce_interval
|
||||
|
||||
if len(self.items) > 1:
|
||||
items = ""
|
||||
for i, item in self.items.items():
|
||||
winning = ""
|
||||
if self.winning_bids.get(i, None):
|
||||
winning = f"(<highlight>{self.winning_bids[i].current_amount}</highlight>)"
|
||||
items += f"{i}. {item} {winning}\n"
|
||||
msg = self.format_auction(f"{items}\n"
|
||||
f"» {self.text.paginate_single(self.get_auction_list())}")
|
||||
self.spam_raid_message(msg)
|
||||
else:
|
||||
item_index = list(self.items.keys())[0]
|
||||
item = self.items[item_index]
|
||||
sql = "SELECT winning_bid FROM auction_log WHERE item_name LIKE ? ORDER BY time DESC LIMIT 5"
|
||||
bids = self.db.query(sql, [item])
|
||||
if bids:
|
||||
avg_win_bid = int(sum(map(lambda x: x.winning_bid, bids)) / len(bids))
|
||||
else:
|
||||
avg_win_bid = 0
|
||||
|
||||
bid_link = self.get_auction_list()
|
||||
bid_link = self.text.paginate_single(ChatBlob("Click to bid", bid_link.msg))
|
||||
msg = self.format_auction(f"1. {item}\n"
|
||||
f"Average winning bid: <highlight>{avg_win_bid}<end>\n"
|
||||
f"» {bid_link}")
|
||||
self.spam_raid_message(msg)
|
||||
|
||||
self.create_next_announce_job()
|
||||
|
||||
def cancel(self, _):
|
||||
self.cancel_job()
|
||||
self.is_running = False
|
||||
return "The Auction got cancelled."
|
||||
|
||||
def add_item(self, item):
|
||||
self.items[self.next_item_index] = item
|
||||
self.next_item_index += 1
|
||||
return self.next_item_index
|
||||
|
||||
def remove_item(self, item_id):
|
||||
del self.items[item_id]
|
||||
del self.winning_bids[item_id]
|
||||
|
||||
def add_bid(self, sender: SenderObj, bid_amount, item_index, request):
|
||||
item_index = item_index or 1
|
||||
item = self.items.get(item_index, None)
|
||||
if not item:
|
||||
return "No item at given index."
|
||||
if bid_amount == 0:
|
||||
return "You tried to bid 0 points. seriously?"
|
||||
|
||||
account = self.account_service.get_account(sender.char_id)
|
||||
main = account.main
|
||||
if self.raid_controller:
|
||||
raider: Raider = self.raid_controller.is_in_raid(main)
|
||||
if type(raider) == Raider:
|
||||
if not raider.is_active:
|
||||
self.bot.send_mass_message(request.sender.char_id,
|
||||
"You are not participating in the raid, and cannot add to the loot.")
|
||||
return
|
||||
elif raider is None:
|
||||
self.bot.send_mass_message(request.sender.char_id,
|
||||
"You are not participating in the raid, and cannot add to the loot.")
|
||||
return
|
||||
if not account:
|
||||
return "You do not have an active account with this bot."
|
||||
elif account.disabled:
|
||||
return "Your account has been frozen. Contact an admin."
|
||||
|
||||
points_used = self.get_points_used(main, item_index)
|
||||
points_available = account.points - points_used
|
||||
|
||||
if points_available == 0:
|
||||
return "You got 0 points... no bids for you."
|
||||
|
||||
if not bid_amount:
|
||||
return "You must specify an amount to bid."
|
||||
|
||||
if isinstance(bid_amount, str) and bid_amount.lower() == "all":
|
||||
bid_amount = points_available
|
||||
|
||||
if bid_amount > points_available:
|
||||
request.reply(f"You dont have enough points. Using {points_available:d} (All points you have)")
|
||||
bid_amount = points_available
|
||||
|
||||
current_amount = 0
|
||||
winning_bid = self.winning_bids.get(item_index, None)
|
||||
if winning_bid:
|
||||
if winning_bid.sender.char_id == sender.char_id:
|
||||
return "You're already holding the highest bid."
|
||||
if bid_amount <= winning_bid.current_amount:
|
||||
return f"Your bid of <highlight>{bid_amount:d}<end> points was not enough. " \
|
||||
f"<highlight>{winning_bid.sender.name}<end> is currently winning with a " \
|
||||
f"bid of <highlight>{winning_bid.current_amount:d}<end>."
|
||||
elif bid_amount <= winning_bid.max_amount:
|
||||
winning_bid.current_amount = bid_amount
|
||||
return f"Your bid of <highlight>{bid_amount}<end> points was not enough. " \
|
||||
f"<highlight>{winning_bid.sender.name}<end> is currently " \
|
||||
f"winning with a bid of <highlight>{winning_bid.current_amount}<end>."
|
||||
else:
|
||||
current_amount = winning_bid.max_amount
|
||||
self.bot.send_private_message(winning_bid.sender.char_id,
|
||||
f"Your bid on {item} has been "
|
||||
f"overtaken by <highlight>{sender.name}<end>.")
|
||||
|
||||
# increment 1 past current max bid
|
||||
current_amount += 1
|
||||
self.winning_bids[item_index] = AuctionBid(sender, account, current_amount, bid_amount)
|
||||
if self.auction_end_time - time.time() < 10:
|
||||
self.auction_end_time += 10
|
||||
self.spam_raid_message(
|
||||
f"<highlight>{sender.name}<end> now holds the leading "
|
||||
f"bid for {item} with a bid of <highlight>{current_amount:d}<end>. [AS: +10 seconds]")
|
||||
|
||||
else:
|
||||
self.spam_raid_message(
|
||||
f"<highlight>{sender.name}<end> now holds the leading bid for {item} "
|
||||
f"with a bid of <highlight>{current_amount:d}<end>.")
|
||||
|
||||
return f"Your max bid of <highlight>{bid_amount:d}<end> points for {item} has put you in the lead. " \
|
||||
f"You have <highlight>{points_available - bid_amount:d}<end> points left for bidding."
|
||||
|
||||
def end(self):
|
||||
self.cancel_job()
|
||||
self.is_running = False
|
||||
|
||||
blob = ""
|
||||
t = int(time.time())
|
||||
# noinspection SqlInsertValues
|
||||
sql = "INSERT INTO auction_log (" \
|
||||
"item_ref, item_name, winner_id, auctioneer_id, " \
|
||||
"time, winning_bid, second_highest_bid) " \
|
||||
"VALUES (?,?,?,?,?,?,?)"
|
||||
items = ""
|
||||
for i, item in self.items.items():
|
||||
winning_bid = self.winning_bids.get(i, None)
|
||||
if winning_bid:
|
||||
self.db.exec(sql, [item, item, winning_bid.sender.char_id, self.auctioneer.char_id, t,
|
||||
winning_bid.current_amount, 0])
|
||||
items += f"{i}. <highlight>{item}</highlight> (<highlight>{winning_bid.sender.name} » " \
|
||||
f"{winning_bid.current_amount}P</highlight>)\n"
|
||||
blob += "%d. %s, won by <highlight>%s<end> with <green>%d<end> points\n" % (
|
||||
i, item, winning_bid.sender.name, winning_bid.current_amount)
|
||||
main_id = self.account_service.get_main(winning_bid.sender.char_id).char_id
|
||||
self.account_service.rem_pts(main_id,
|
||||
winning_bid.current_amount,
|
||||
f"won {item}",
|
||||
self.auctioneer.char_id)
|
||||
else:
|
||||
items += f"{i}. <highlight>{item}</highlight> (<red>FFA</red>)\n"
|
||||
blob += "%d. %s, no bids made\n" % (i, item)
|
||||
|
||||
result_blob = self.text.paginate_single(ChatBlob("The Auction results", blob))
|
||||
msg = self.format_auction(f"{items}"
|
||||
f"» {result_blob}")
|
||||
self.spam_raid_message(msg)
|
||||
|
||||
def remove_bid(self, char_id, item_id):
|
||||
pass
|
||||
|
||||
def spam_raid_message(self, message):
|
||||
self.bot.send_private_channel_message(message, fire_outgoing_event=False)
|
||||
|
||||
def get_auction_list(self):
|
||||
blob = ""
|
||||
for i, item in self.items.items():
|
||||
if item[:2] == "<a" and item[-4:] == "</a>":
|
||||
item = re.findall(r"(([^<]+)?<a href=[\"\']itemref://(\d+)/(\d+)/(\d+)[\"\']>([^<]+)</a>([^<]+)?)",
|
||||
item)
|
||||
img = ""
|
||||
if isinstance(item[0], tuple):
|
||||
imgid = self.db.query_single("SELECT icon from aodb where lowid=? and highid=?",
|
||||
[item[0][2], item[0][3]])
|
||||
if imgid is not None:
|
||||
img = self.text.make_image(imgid.get("icon")) + " - "
|
||||
blob += "%d. %s%s" % (i, img, item[0][0])
|
||||
|
||||
else:
|
||||
img = ""
|
||||
blob += f"{i:d}. {img}{item}"
|
||||
winning_bid = self.winning_bids.get(i, None)
|
||||
if winning_bid:
|
||||
blob += f"<br><tab><highlight>{winning_bid.sender.name}<end> has the " \
|
||||
f"winning bid of <highlight>{winning_bid.current_amount:d}<end>\n["
|
||||
blob += self.text.make_chatcmd("bid +1", f"/tell <myname> bid {winning_bid.current_amount + 1} {i}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid +10", f"/tell <myname> bid {winning_bid.current_amount + 10} {i}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid +25", f"/tell <myname> bid {winning_bid.current_amount + 25} {i}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid +100", f"/tell <myname> bid {winning_bid.current_amount + 100} {i}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid +500", f"/tell <myname> bid {winning_bid.current_amount + 500} {i}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid Max", f"/tell <myname> bid all {i}")
|
||||
blob += "]\n────────────────────────────────\n"
|
||||
else:
|
||||
blob += "<br><tab><green>No bidders<end>\n["
|
||||
blob += self.text.make_chatcmd("bid 1", f"/tell <myname> bid 1 {i:d}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid 10", f"/tell <myname> bid 10 {i:d}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid 25", f"/tell <myname> bid 25 {i:d}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid 100", f"/tell <myname> bid 100 {i:d}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid 500", f"/tell <myname> bid 500 {i:d}")
|
||||
blob += "]<tab>["
|
||||
blob += self.text.make_chatcmd("bid Max", f"/tell <myname> bid all {i:d}")
|
||||
blob += "]\n────────────────────────────────\n"
|
||||
|
||||
return ChatBlob(f"The Auction list ({len(self.items):d})", blob)
|
||||
|
||||
def get_points_used(self, main_id, item_index):
|
||||
points_used = 0
|
||||
for index, bid in self.winning_bids.items():
|
||||
if index != item_index and bid.account.char_id == main_id:
|
||||
points_used += bid.max_amount
|
||||
|
||||
return points_used
|
||||
|
||||
def auction_announce(self, _):
|
||||
time_left = self.time_left()
|
||||
if time_left <= 0:
|
||||
self.end()
|
||||
return
|
||||
|
||||
item_count = len(self.items)
|
||||
if item_count > 1:
|
||||
items = ""
|
||||
for i, item in self.items.items():
|
||||
winning = ""
|
||||
if self.winning_bids.get(i, None):
|
||||
winning = f"(<highlight>{self.winning_bids[i].sender.name} » " \
|
||||
f"{self.winning_bids[i].current_amount}P</highlight>)"
|
||||
items += f"{i}. {item} {winning}\n"
|
||||
|
||||
msg = self.format_auction(f"{items}\n"
|
||||
f"» {self.text.paginate_single(self.get_auction_list())}\n"
|
||||
f"<highlight>{time_left}</highlight> seconds left")
|
||||
|
||||
else:
|
||||
item_index = list(self.items.keys())[0]
|
||||
item = self.items[item_index]
|
||||
winning_bid = self.winning_bids.get(item_index, None)
|
||||
|
||||
if winning_bid:
|
||||
winner = f"<highlight>{winning_bid.sender.name}<end> now holds the " \
|
||||
f"leading bid with a bid of <highlight>{winning_bid.current_amount:d}<end>."
|
||||
else:
|
||||
winner = "No bids made."
|
||||
msg = self.format_auction(f"1. {item}\n"
|
||||
f"{winner}\n"
|
||||
f"» {self.text.paginate_single(self.get_auction_list())}\n"
|
||||
f"<highlight>{time_left}</highlight> seconds left")
|
||||
|
||||
self.spam_raid_message(msg)
|
||||
self.create_next_announce_job()
|
||||
|
||||
def time_left(self):
|
||||
t = int(time.time())
|
||||
time_left = self.auction_end_time - t
|
||||
if time_left < 0:
|
||||
time_left = 0
|
||||
|
||||
return time_left
|
||||
|
||||
def create_next_announce_job(self):
|
||||
t = int(time.time())
|
||||
time_remaining = self.auction_end_time - t
|
||||
mod = time_remaining % self.announce_interval
|
||||
if mod == 0:
|
||||
mod = self.announce_interval
|
||||
|
||||
next_job_t = t + mod
|
||||
self.job_id = self.job_scheduler.scheduled_job(self.auction_announce, next_job_t)
|
||||
|
||||
def cancel_job(self):
|
||||
if self.job_id:
|
||||
self.job_scheduler.cancel_job(self.job_id)
|
||||
self.job_id = None
|
||||
|
||||
def format_auction(self, message):
|
||||
return f"<yellow>\n" \
|
||||
f"────────[ Auction ]────────\n" \
|
||||
f"{message}\n" \
|
||||
f"────────[ Auction ]────────</yellow>"
|
||||
Reference in New Issue
Block a user