Initial Release of IGNCore version 2.5

This commit is contained in:
2021-08-09 13:18:56 +02:00
commit a83d98c47e
910 changed files with 224171 additions and 0 deletions
@@ -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>"